Browse Source

智能合约基础构造完成。

龚成明 3 years ago
parent
commit
cf059db9ce
6 changed files with 154 additions and 3 deletions
  1. 2 1
      config/contracts.ts
  2. 2 2
      contracts/Calc.sol
  3. 53 0
      contracts/Flash.sol
  4. 53 0
      contracts/base/Address.sol
  5. 26 0
      contracts/base/TransferHelper.sol
  6. 18 0
      test/Univ3Test.ts

+ 2 - 1
config/contracts.ts

@@ -4,7 +4,8 @@ export default {
   USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
   UNIV3: '0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45',
   UNIV3_FACTORY: '0x1F98431c8aD98523631AE4a59f267346ea31F984',
+  QUOTER: '0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6',
   ZERO: '0x0000000000000000000000000000000000000000',
   CALC: '0x30c34b111121aCDb423eF2C0e39235Dc68a793A4',
-  QUOTER: '0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6'
+  FLASH: ''
 }

+ 2 - 2
contracts/Calc.sol

@@ -1,9 +1,9 @@
+//SPDX-License-Identifier: Unlicense
+
 pragma solidity ^0.7.6;
 
 import '@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol';
-
 import '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';
-
 import 'hardhat/console.sol';
 
 contract Calc {

+ 53 - 0
contracts/Flash.sol

@@ -0,0 +1,53 @@
+//SPDX-License-Identifier: Unlicense
+pragma solidity ^0.7.6;
+pragma abicoder v2;
+
+import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
+import '@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol';
+import './base/TransferHelper.sol';
+import './base/Address.sol';
+
+contract Flash {
+    mapping(address => bool) private adminMap;
+    mapping(address => mapping(address => uint256)) private approveMap;
+    address private owner;
+
+    constructor() {
+        owner = msg.sender;
+
+        adminMap[owner] = true;
+        adminMap[address(this)] = true;
+    }
+
+    modifier onlyOwner() {
+        require(msg.sender == owner || msg.sender == address(this), 'Not is owner.');
+        _;
+    }
+
+    modifier onlyMaster() {
+        require(adminMap[msg.sender], 'Not is master.');
+        _;
+    }
+
+    function addAdmin(address _addr) public onlyOwner {
+        adminMap[_addr] = true;
+    }
+
+    function approve(uint256 _volume, address _token, address _to) public onlyOwner {
+        TransferHelper.safeApprove(_token, _to, _volume);
+        approveMap[_to][_token] = _volume;
+    }
+
+    function withdraw(address _token) public onlyOwner {
+        uint256 token_balance = IERC20(_token).balanceOf(address(this));
+        TransferHelper.safeTransfer(_token, owner, token_balance);
+    }
+
+    struct FlashLoanParams {
+        address pool;
+    }
+
+    function flashLoan(FlashLoanParams memory params) external pure returns (uint256 num){
+        return 0;
+    }
+}

+ 53 - 0
contracts/base/Address.sol

@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+pragma solidity ^0.7.6;
+pragma abicoder v2;
+
+library Address {
+    function isContract(address account) internal view returns (bool) {
+        uint256 size;
+        assembly { size := extcodesize(account) }
+        return size > 0;
+    }
+
+    function sendValue(address payable recipient, uint256 amount) internal {
+        require(address(this).balance >= amount, "Address: insufficient balance");
+
+        (bool success, ) = recipient.call{ value: amount }("");
+        require(success, "Address: unable to send value, recipient may have reverted");
+    }
+
+    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
+      return functionCall(target, data, "Address: low-level call failed");
+    }
+
+    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
+        return functionCallWithValue(target, data, 0, errorMessage);
+    }
+
+    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
+        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
+    }
+
+    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
+        require(address(this).balance >= value, "Address: insufficient balance for call");
+        require(isContract(target), "Address: call to non-contract");
+
+        (bool success, bytes memory returndata) = target.call{ value: value }(data);
+        return _verifyCallResult(success, returndata, errorMessage);
+    }
+
+    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
+        if (success) {
+            return returndata;
+        } else {
+            if (returndata.length > 0) {
+                assembly {
+                    let returndata_size := mload(returndata)
+                    revert(add(32, returndata), returndata_size)
+                }
+            } else {
+                revert(errorMessage);
+            }
+        }
+    }
+}

+ 26 - 0
contracts/base/TransferHelper.sol

@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+pragma solidity ^0.7.6;
+pragma abicoder v2;
+
+// base library
+library TransferHelper {
+    function safeApprove(address token, address to, uint256 value) internal {
+        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
+        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED.');
+    }
+
+    function safeTransfer(address token, address to, uint value) internal {
+        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
+        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED.');
+    }
+
+    function safeTransferFrom(address token, address from, address to, uint value) internal {
+        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
+        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED.');
+    }
+
+    function safeTransferETH(address to, uint value) internal {
+        (bool success,) = to.call{value: value}(new bytes(0));
+        require(success, 'TransferHelper: ETH_TRANSFER_FAILED');
+    }
+}

+ 18 - 0
test/Univ3Test.ts

@@ -67,4 +67,22 @@ describe('Uniswap v3 test', () => {
             .quoteExactInputSingle(contracts.WETH, contracts.USDT, fee._30_per_10000, inAmount, 0)
             .call().then(console.log)
     })
+
+    it('Univ3 swap test', async () => {
+        const FLASH_ABI = require('../artifacts/contracts/Flash.sol').abi
+
+        let flash = new web3.eth.Contract(FLASH_ABI, contracts.FLASH)
+
+        let rawTx = {
+            from: deployer.address,
+            nonce: await web3.eth.getTransactionCount(deployer.address),
+            gasPrice: web3.utils.toWei('2', 'gwei'),
+            gasLimit: 1e6
+        }
+
+        const WETH_USDT_POOL_CONTRACT = '0x4e68Ccd3E89f51C3074ca5072bbAC773960dFa36'
+        await flash.methods
+            .swap()
+            .send(rawTx).then(console.log)
+    })
 })