├── .circleci └── config.yml ├── .eslintrc.json ├── .github └── workflows │ └── abigen.yml ├── .gitignore ├── LICENSE ├── README.md ├── Security-Audit-Report-31052023.md ├── abi ├── BurnableToken.js ├── BurnableToken.json ├── IAugustusSwapper.js ├── IAugustusSwapper.json ├── IBarn.js ├── IBarn.json ├── IBurnableToken.js ├── IBurnableToken.json ├── IERC20.js ├── IERC20.json ├── IParams.js ├── IParams.json ├── IParaswap.js ├── IParaswap.json ├── ISwapContract.js ├── ISwapContract.json ├── ISwapRewards.js ├── ISwapRewards.json ├── ITokenTransferProxy.js ├── ITokenTransferProxy.json ├── IWETH.js ├── IWETH.json ├── LPToken.js ├── LPToken.json ├── Ownable.js ├── Ownable.json ├── Params.js ├── Params.json ├── SwapContract.js ├── SwapContract.json ├── SwapRewards.js ├── SwapRewards.json ├── SwingbyToken.js ├── SwingbyToken.json ├── sbBTCPool.js └── sbBTCPool.json ├── abigo ├── BurnableToken.go ├── IAugustusSwapper.go ├── IBarn.go ├── IBurnableToken.go ├── IERC20.go ├── IParams.go ├── IParaswap.go ├── ISwapContract.go ├── ISwapRewards.go ├── ITokenTransferProxy.go ├── IWETH.go ├── LPToken.go ├── Ownable.go ├── Params.go ├── SwapContract.go ├── SwapRewards.go ├── SwingbyToken.go └── sbBTCPool.go ├── args.js ├── contracts ├── BurnableToken.sol ├── LPToken.sol ├── Params.sol ├── SwapContract.sol ├── SwapRewards.sol ├── SwingbyToken.sol ├── interfaces │ ├── IAugustusSwapper.sol │ ├── IBarn.sol │ ├── IBurnableToken.sol │ ├── IERC20.sol │ ├── IParams.sol │ ├── IParaswap.sol │ ├── ISwapContract.sol │ ├── ISwapRewards.sol │ ├── ITokenTransferProxy.sol │ ├── IWETH.sol │ └── lib │ │ ├── Address.sol │ │ ├── SafeERC20.sol │ │ └── Utils.sol └── sbBTCPool.sol ├── docs ├── Diagrams │ ├── SkyPools Diagram.png │ ├── SkypoolsDiagram.drawio │ ├── SkypoolsVisual.drawio │ ├── SkypoolsVisual_Flow 1.drawio.png │ ├── SkypoolsVisual_Flow 1.drawio.xml │ ├── SkypoolsVisual_Flow 2.drawio.png │ ├── SkypoolsVisual_Flow 2.drawio.xml │ ├── SwapContractDetailed.png │ ├── UML_Diagram.dot │ ├── UML_Image.png │ └── UML_SVG.svg ├── Skybridge Security Audit Report - Red4Sec.pdf ├── Skybridge Security Audit Report.pdf ├── lp-token-rate-logic.md ├── readme.md ├── support_bsc.md └── swap_contract_spec.md ├── hardhat.config.js ├── package-lock.json ├── package.json ├── scripts ├── addFloat.js ├── addFloatNew.js ├── addNode.js ├── burnToken.js ├── deploy-goerli.js ├── deploy-mainnet.js ├── deploy-ropsten.js ├── deploy-sbBTCPool.ts ├── deployParams.js ├── deploySwapRewards.js ├── deploySwingbyToken.js ├── erc20ABI.js ├── generateGoBindings.js ├── mintToken.js ├── moveLPTOwner.js ├── moveSCOwner.js ├── paraswap.js ├── removeFloat.js ├── sbBTCchecks.js ├── showNodes.js ├── swapBTC2WBTC.js ├── swapWBTC2BTC.js ├── testnet.js └── transferOwner.js ├── test ├── old │ ├── testSkyPools.js │ └── testSkyPoolsV2.js ├── testAddNode.js ├── testLPToken.js ├── testSkyPoolsV2.js ├── testSwapContract.js └── testSwapContractFactory.js ├── truffle-config.js └── web3_test ├── testAddNode.js ├── testLPToken.js ├── testSwapContract.js └── testSwapContractFactory.js /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: circleci/python:3.8-node 6 | steps: 7 | - checkout 8 | - run: 9 | name: npm install 10 | command: | 11 | node --version 12 | npm install 13 | - persist_to_workspace: 14 | root: . 15 | paths: 16 | - . 17 | 18 | test: 19 | docker: 20 | - image: circleci/python:3.8-node 21 | steps: 22 | - attach_workspace: 23 | at: . 24 | - run: 25 | name: test 26 | command: | 27 | npm run test 28 | - persist_to_workspace: 29 | root: . 30 | paths: 31 | - . 32 | 33 | audit: 34 | docker: 35 | - image: circleci/python:3.8-node 36 | steps: 37 | - attach_workspace: 38 | at: . 39 | - run: 40 | name: Setup virtual environment 41 | command: python -m virtualenv venv 42 | - run: 43 | name: Install MythX CLI 44 | command: | 45 | . venv/bin/activate 46 | pip install mythx-cli 47 | - run: 48 | name: Analyze with MythX 49 | command: | 50 | . venv/bin/activate 51 | mythx --yes analyze --mode standard --async --solc-version 0.8.19 --remap-import @openzeppelin/=$(pwd)/node_modules/@openzeppelin/ contracts/ 52 | 53 | workflows: 54 | version: 2 55 | build_test_audit: 56 | jobs: 57 | - build 58 | - test: 59 | requires: 60 | - build 61 | - audit: 62 | requires: 63 | - test 64 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true 5 | }, 6 | "parserOptions": { 7 | "ecmaVersion": 12, 8 | "sourceType": "module" 9 | }, 10 | "rules": { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /.github/workflows/abigen.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | 11 | build: 12 | name: Build 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v2 16 | - uses: bahmutov/npm-install@v1 17 | 18 | - name: Use Go 1.x 19 | uses: actions/setup-go@v2 20 | with: 21 | go-version: ^1.13 22 | 23 | - name: Use Node.js ${{ matrix.node-version }} 24 | uses: actions/setup-node@v1 25 | with: 26 | node-version: ${{ matrix.node-version }} 27 | 28 | - name: Download go-ethereum 29 | run: git clone https://github.com/ethereum/go-ethereum /tmp/go-ethereum && cd /tmp/go-ethereum && go install ./cmd/abigen 30 | 31 | - name: Run truffle compile 32 | run: npm install && npm run compile 33 | 34 | - name: Run abigen 35 | run: npm run gen-go 36 | 37 | - name: Commit files 38 | env: 39 | GITHUB_TOKEN: ${{ secrets.github_token }} 40 | run: | 41 | git config --local user.email "action@github.com" 42 | git config --local user.name "GitHub Action" 43 | git remote set-url origin https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git 44 | git checkout main 45 | git add . 46 | git commit -m "Auto build" -a || echo "No files to commit" 47 | git push origin HEAD 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | cache 3 | artifacts 4 | build/* 5 | abigenBindings/bin 6 | .DS_Store 7 | .env 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Skybridge-contract-v3 2 | 3 | ## Environment 4 | - hardhat (v2.14.0) 5 | - solidity (v0.8.19) 6 | 7 | ## Deployment Order 8 | 1. Deploy sbBTCPool nodeRewards contracts 9 | 2. Deploy LP token and swap contract (initial liquidiy setup if need) 10 | 3. Initialize sbBTCPool and nodeRewards 11 | 4. Mint LPT to users (if need) 12 | 5. Set old LPT token for convert -- they can convert to new token with burning old token. 13 | 6. Transferring owner of new LPT to swap contract 14 | 15 | ## Build contract 16 | ``` 17 | $ npx hardhat compile 18 | ``` 19 | 20 | ## Test 21 | ``` 22 | $ npx hardhat test ./test/testSwapContract.js 23 | ``` 24 | 25 | ## Mainnet contracts 26 | ``` 27 | TBA 28 | ``` 29 | 30 | ## Testnet contracts (goerli) 31 | ``` 32 | SwapContract 33 | https://goerli.etherscan.io/address/0x9e6ba6e811665849f03f56c1f22a8894aebb3993 34 | LPToken 35 | https://goerli.etherscan.io/address/0xb10c6c5a6baf604206867cb229baddab02eea602 36 | SwapRewards 37 | https://goerli.etherscan.io/address/0xf4c381d077272295641f8a53d850d9a8125e0e94 38 | BTCT 39 | https://goerli.etherscan.io/address/0xeb47a21c1fc00d1e863019906df1771b80dbe182 40 | sbBTCPool 41 | https://goerli.etherscan.io/address/0xd60126017fdf906668cfe5327c566c65e7f061ba 42 | Barn 43 | https://goerli.etherscan.io/address/0x009cc14ce70b2e667984c2276490d56ae3234c43 44 | ``` 45 | -------------------------------------------------------------------------------- /abi/IBarn.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "address", 6 | "name": "user", 7 | "type": "address" 8 | }, 9 | { 10 | "internalType": "uint256", 11 | "name": "timestamp", 12 | "type": "uint256" 13 | } 14 | ], 15 | "name": "balanceAtTs", 16 | "outputs": [ 17 | { 18 | "internalType": "uint256", 19 | "name": "", 20 | "type": "uint256" 21 | } 22 | ], 23 | "stateMutability": "view", 24 | "type": "function" 25 | }, 26 | { 27 | "inputs": [ 28 | { 29 | "internalType": "address", 30 | "name": "user", 31 | "type": "address" 32 | } 33 | ], 34 | "name": "balanceOf", 35 | "outputs": [ 36 | { 37 | "internalType": "uint256", 38 | "name": "", 39 | "type": "uint256" 40 | } 41 | ], 42 | "stateMutability": "view", 43 | "type": "function" 44 | } 45 | ]; 46 | -------------------------------------------------------------------------------- /abi/IBarn.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "address", 6 | "name": "user", 7 | "type": "address" 8 | }, 9 | { 10 | "internalType": "uint256", 11 | "name": "timestamp", 12 | "type": "uint256" 13 | } 14 | ], 15 | "name": "balanceAtTs", 16 | "outputs": [ 17 | { 18 | "internalType": "uint256", 19 | "name": "", 20 | "type": "uint256" 21 | } 22 | ], 23 | "stateMutability": "view", 24 | "type": "function" 25 | }, 26 | { 27 | "inputs": [ 28 | { 29 | "internalType": "address", 30 | "name": "user", 31 | "type": "address" 32 | } 33 | ], 34 | "name": "balanceOf", 35 | "outputs": [ 36 | { 37 | "internalType": "uint256", 38 | "name": "", 39 | "type": "uint256" 40 | } 41 | ], 42 | "stateMutability": "view", 43 | "type": "function" 44 | } 45 | ] 46 | -------------------------------------------------------------------------------- /abi/IBurnableToken.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | "anonymous": false, 4 | "inputs": [ 5 | { 6 | "indexed": true, 7 | "internalType": "address", 8 | "name": "owner", 9 | "type": "address" 10 | }, 11 | { 12 | "indexed": true, 13 | "internalType": "address", 14 | "name": "spender", 15 | "type": "address" 16 | }, 17 | { 18 | "indexed": false, 19 | "internalType": "uint256", 20 | "name": "value", 21 | "type": "uint256" 22 | } 23 | ], 24 | "name": "Approval", 25 | "type": "event" 26 | }, 27 | { 28 | "anonymous": false, 29 | "inputs": [ 30 | { 31 | "indexed": true, 32 | "internalType": "address", 33 | "name": "from", 34 | "type": "address" 35 | }, 36 | { 37 | "indexed": true, 38 | "internalType": "address", 39 | "name": "to", 40 | "type": "address" 41 | }, 42 | { 43 | "indexed": false, 44 | "internalType": "uint256", 45 | "name": "value", 46 | "type": "uint256" 47 | } 48 | ], 49 | "name": "Transfer", 50 | "type": "event" 51 | }, 52 | { 53 | "inputs": [ 54 | { 55 | "internalType": "address", 56 | "name": "_owner", 57 | "type": "address" 58 | }, 59 | { 60 | "internalType": "address", 61 | "name": "spender", 62 | "type": "address" 63 | } 64 | ], 65 | "name": "allowance", 66 | "outputs": [ 67 | { 68 | "internalType": "uint256", 69 | "name": "", 70 | "type": "uint256" 71 | } 72 | ], 73 | "stateMutability": "view", 74 | "type": "function" 75 | }, 76 | { 77 | "inputs": [ 78 | { 79 | "internalType": "address", 80 | "name": "spender", 81 | "type": "address" 82 | }, 83 | { 84 | "internalType": "uint256", 85 | "name": "amount", 86 | "type": "uint256" 87 | } 88 | ], 89 | "name": "approve", 90 | "outputs": [ 91 | { 92 | "internalType": "bool", 93 | "name": "", 94 | "type": "bool" 95 | } 96 | ], 97 | "stateMutability": "nonpayable", 98 | "type": "function" 99 | }, 100 | { 101 | "inputs": [ 102 | { 103 | "internalType": "address", 104 | "name": "account", 105 | "type": "address" 106 | } 107 | ], 108 | "name": "balanceOf", 109 | "outputs": [ 110 | { 111 | "internalType": "uint256", 112 | "name": "", 113 | "type": "uint256" 114 | } 115 | ], 116 | "stateMutability": "view", 117 | "type": "function" 118 | }, 119 | { 120 | "inputs": [ 121 | { 122 | "internalType": "uint256", 123 | "name": "amount", 124 | "type": "uint256" 125 | } 126 | ], 127 | "name": "burn", 128 | "outputs": [ 129 | { 130 | "internalType": "bool", 131 | "name": "", 132 | "type": "bool" 133 | } 134 | ], 135 | "stateMutability": "nonpayable", 136 | "type": "function" 137 | }, 138 | { 139 | "inputs": [], 140 | "name": "decimals", 141 | "outputs": [ 142 | { 143 | "internalType": "uint8", 144 | "name": "", 145 | "type": "uint8" 146 | } 147 | ], 148 | "stateMutability": "view", 149 | "type": "function" 150 | }, 151 | { 152 | "inputs": [], 153 | "name": "getOwner", 154 | "outputs": [ 155 | { 156 | "internalType": "address", 157 | "name": "", 158 | "type": "address" 159 | } 160 | ], 161 | "stateMutability": "view", 162 | "type": "function" 163 | }, 164 | { 165 | "inputs": [ 166 | { 167 | "internalType": "address", 168 | "name": "target", 169 | "type": "address" 170 | }, 171 | { 172 | "internalType": "uint256", 173 | "name": "amount", 174 | "type": "uint256" 175 | } 176 | ], 177 | "name": "mint", 178 | "outputs": [ 179 | { 180 | "internalType": "bool", 181 | "name": "", 182 | "type": "bool" 183 | } 184 | ], 185 | "stateMutability": "nonpayable", 186 | "type": "function" 187 | }, 188 | { 189 | "inputs": [], 190 | "name": "mintable", 191 | "outputs": [ 192 | { 193 | "internalType": "bool", 194 | "name": "", 195 | "type": "bool" 196 | } 197 | ], 198 | "stateMutability": "nonpayable", 199 | "type": "function" 200 | }, 201 | { 202 | "inputs": [], 203 | "name": "name", 204 | "outputs": [ 205 | { 206 | "internalType": "string", 207 | "name": "", 208 | "type": "string" 209 | } 210 | ], 211 | "stateMutability": "view", 212 | "type": "function" 213 | }, 214 | { 215 | "inputs": [], 216 | "name": "symbol", 217 | "outputs": [ 218 | { 219 | "internalType": "string", 220 | "name": "", 221 | "type": "string" 222 | } 223 | ], 224 | "stateMutability": "view", 225 | "type": "function" 226 | }, 227 | { 228 | "inputs": [], 229 | "name": "totalSupply", 230 | "outputs": [ 231 | { 232 | "internalType": "uint256", 233 | "name": "", 234 | "type": "uint256" 235 | } 236 | ], 237 | "stateMutability": "view", 238 | "type": "function" 239 | }, 240 | { 241 | "inputs": [ 242 | { 243 | "internalType": "address", 244 | "name": "recipient", 245 | "type": "address" 246 | }, 247 | { 248 | "internalType": "uint256", 249 | "name": "amount", 250 | "type": "uint256" 251 | } 252 | ], 253 | "name": "transfer", 254 | "outputs": [ 255 | { 256 | "internalType": "bool", 257 | "name": "", 258 | "type": "bool" 259 | } 260 | ], 261 | "stateMutability": "nonpayable", 262 | "type": "function" 263 | }, 264 | { 265 | "inputs": [ 266 | { 267 | "internalType": "address", 268 | "name": "sender", 269 | "type": "address" 270 | }, 271 | { 272 | "internalType": "address", 273 | "name": "recipient", 274 | "type": "address" 275 | }, 276 | { 277 | "internalType": "uint256", 278 | "name": "amount", 279 | "type": "uint256" 280 | } 281 | ], 282 | "name": "transferFrom", 283 | "outputs": [ 284 | { 285 | "internalType": "bool", 286 | "name": "", 287 | "type": "bool" 288 | } 289 | ], 290 | "stateMutability": "nonpayable", 291 | "type": "function" 292 | } 293 | ]; 294 | -------------------------------------------------------------------------------- /abi/IBurnableToken.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "anonymous": false, 4 | "inputs": [ 5 | { 6 | "indexed": true, 7 | "internalType": "address", 8 | "name": "owner", 9 | "type": "address" 10 | }, 11 | { 12 | "indexed": true, 13 | "internalType": "address", 14 | "name": "spender", 15 | "type": "address" 16 | }, 17 | { 18 | "indexed": false, 19 | "internalType": "uint256", 20 | "name": "value", 21 | "type": "uint256" 22 | } 23 | ], 24 | "name": "Approval", 25 | "type": "event" 26 | }, 27 | { 28 | "anonymous": false, 29 | "inputs": [ 30 | { 31 | "indexed": true, 32 | "internalType": "address", 33 | "name": "from", 34 | "type": "address" 35 | }, 36 | { 37 | "indexed": true, 38 | "internalType": "address", 39 | "name": "to", 40 | "type": "address" 41 | }, 42 | { 43 | "indexed": false, 44 | "internalType": "uint256", 45 | "name": "value", 46 | "type": "uint256" 47 | } 48 | ], 49 | "name": "Transfer", 50 | "type": "event" 51 | }, 52 | { 53 | "inputs": [ 54 | { 55 | "internalType": "address", 56 | "name": "_owner", 57 | "type": "address" 58 | }, 59 | { 60 | "internalType": "address", 61 | "name": "spender", 62 | "type": "address" 63 | } 64 | ], 65 | "name": "allowance", 66 | "outputs": [ 67 | { 68 | "internalType": "uint256", 69 | "name": "", 70 | "type": "uint256" 71 | } 72 | ], 73 | "stateMutability": "view", 74 | "type": "function" 75 | }, 76 | { 77 | "inputs": [ 78 | { 79 | "internalType": "address", 80 | "name": "spender", 81 | "type": "address" 82 | }, 83 | { 84 | "internalType": "uint256", 85 | "name": "amount", 86 | "type": "uint256" 87 | } 88 | ], 89 | "name": "approve", 90 | "outputs": [ 91 | { 92 | "internalType": "bool", 93 | "name": "", 94 | "type": "bool" 95 | } 96 | ], 97 | "stateMutability": "nonpayable", 98 | "type": "function" 99 | }, 100 | { 101 | "inputs": [ 102 | { 103 | "internalType": "address", 104 | "name": "account", 105 | "type": "address" 106 | } 107 | ], 108 | "name": "balanceOf", 109 | "outputs": [ 110 | { 111 | "internalType": "uint256", 112 | "name": "", 113 | "type": "uint256" 114 | } 115 | ], 116 | "stateMutability": "view", 117 | "type": "function" 118 | }, 119 | { 120 | "inputs": [ 121 | { 122 | "internalType": "uint256", 123 | "name": "amount", 124 | "type": "uint256" 125 | } 126 | ], 127 | "name": "burn", 128 | "outputs": [ 129 | { 130 | "internalType": "bool", 131 | "name": "", 132 | "type": "bool" 133 | } 134 | ], 135 | "stateMutability": "nonpayable", 136 | "type": "function" 137 | }, 138 | { 139 | "inputs": [], 140 | "name": "decimals", 141 | "outputs": [ 142 | { 143 | "internalType": "uint8", 144 | "name": "", 145 | "type": "uint8" 146 | } 147 | ], 148 | "stateMutability": "view", 149 | "type": "function" 150 | }, 151 | { 152 | "inputs": [], 153 | "name": "getOwner", 154 | "outputs": [ 155 | { 156 | "internalType": "address", 157 | "name": "", 158 | "type": "address" 159 | } 160 | ], 161 | "stateMutability": "view", 162 | "type": "function" 163 | }, 164 | { 165 | "inputs": [ 166 | { 167 | "internalType": "address", 168 | "name": "target", 169 | "type": "address" 170 | }, 171 | { 172 | "internalType": "uint256", 173 | "name": "amount", 174 | "type": "uint256" 175 | } 176 | ], 177 | "name": "mint", 178 | "outputs": [ 179 | { 180 | "internalType": "bool", 181 | "name": "", 182 | "type": "bool" 183 | } 184 | ], 185 | "stateMutability": "nonpayable", 186 | "type": "function" 187 | }, 188 | { 189 | "inputs": [], 190 | "name": "mintable", 191 | "outputs": [ 192 | { 193 | "internalType": "bool", 194 | "name": "", 195 | "type": "bool" 196 | } 197 | ], 198 | "stateMutability": "nonpayable", 199 | "type": "function" 200 | }, 201 | { 202 | "inputs": [], 203 | "name": "name", 204 | "outputs": [ 205 | { 206 | "internalType": "string", 207 | "name": "", 208 | "type": "string" 209 | } 210 | ], 211 | "stateMutability": "view", 212 | "type": "function" 213 | }, 214 | { 215 | "inputs": [], 216 | "name": "symbol", 217 | "outputs": [ 218 | { 219 | "internalType": "string", 220 | "name": "", 221 | "type": "string" 222 | } 223 | ], 224 | "stateMutability": "view", 225 | "type": "function" 226 | }, 227 | { 228 | "inputs": [], 229 | "name": "totalSupply", 230 | "outputs": [ 231 | { 232 | "internalType": "uint256", 233 | "name": "", 234 | "type": "uint256" 235 | } 236 | ], 237 | "stateMutability": "view", 238 | "type": "function" 239 | }, 240 | { 241 | "inputs": [ 242 | { 243 | "internalType": "address", 244 | "name": "recipient", 245 | "type": "address" 246 | }, 247 | { 248 | "internalType": "uint256", 249 | "name": "amount", 250 | "type": "uint256" 251 | } 252 | ], 253 | "name": "transfer", 254 | "outputs": [ 255 | { 256 | "internalType": "bool", 257 | "name": "", 258 | "type": "bool" 259 | } 260 | ], 261 | "stateMutability": "nonpayable", 262 | "type": "function" 263 | }, 264 | { 265 | "inputs": [ 266 | { 267 | "internalType": "address", 268 | "name": "sender", 269 | "type": "address" 270 | }, 271 | { 272 | "internalType": "address", 273 | "name": "recipient", 274 | "type": "address" 275 | }, 276 | { 277 | "internalType": "uint256", 278 | "name": "amount", 279 | "type": "uint256" 280 | } 281 | ], 282 | "name": "transferFrom", 283 | "outputs": [ 284 | { 285 | "internalType": "bool", 286 | "name": "", 287 | "type": "bool" 288 | } 289 | ], 290 | "stateMutability": "nonpayable", 291 | "type": "function" 292 | } 293 | ] 294 | -------------------------------------------------------------------------------- /abi/IERC20.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | "anonymous": false, 4 | "inputs": [ 5 | { 6 | "indexed": true, 7 | "internalType": "address", 8 | "name": "owner", 9 | "type": "address" 10 | }, 11 | { 12 | "indexed": true, 13 | "internalType": "address", 14 | "name": "spender", 15 | "type": "address" 16 | }, 17 | { 18 | "indexed": false, 19 | "internalType": "uint256", 20 | "name": "value", 21 | "type": "uint256" 22 | } 23 | ], 24 | "name": "Approval", 25 | "type": "event" 26 | }, 27 | { 28 | "anonymous": false, 29 | "inputs": [ 30 | { 31 | "indexed": true, 32 | "internalType": "address", 33 | "name": "from", 34 | "type": "address" 35 | }, 36 | { 37 | "indexed": true, 38 | "internalType": "address", 39 | "name": "to", 40 | "type": "address" 41 | }, 42 | { 43 | "indexed": false, 44 | "internalType": "uint256", 45 | "name": "value", 46 | "type": "uint256" 47 | } 48 | ], 49 | "name": "Transfer", 50 | "type": "event" 51 | }, 52 | { 53 | "inputs": [ 54 | { 55 | "internalType": "address", 56 | "name": "_owner", 57 | "type": "address" 58 | }, 59 | { 60 | "internalType": "address", 61 | "name": "spender", 62 | "type": "address" 63 | } 64 | ], 65 | "name": "allowance", 66 | "outputs": [ 67 | { 68 | "internalType": "uint256", 69 | "name": "", 70 | "type": "uint256" 71 | } 72 | ], 73 | "stateMutability": "view", 74 | "type": "function" 75 | }, 76 | { 77 | "inputs": [ 78 | { 79 | "internalType": "address", 80 | "name": "spender", 81 | "type": "address" 82 | }, 83 | { 84 | "internalType": "uint256", 85 | "name": "amount", 86 | "type": "uint256" 87 | } 88 | ], 89 | "name": "approve", 90 | "outputs": [ 91 | { 92 | "internalType": "bool", 93 | "name": "", 94 | "type": "bool" 95 | } 96 | ], 97 | "stateMutability": "nonpayable", 98 | "type": "function" 99 | }, 100 | { 101 | "inputs": [ 102 | { 103 | "internalType": "address", 104 | "name": "account", 105 | "type": "address" 106 | } 107 | ], 108 | "name": "balanceOf", 109 | "outputs": [ 110 | { 111 | "internalType": "uint256", 112 | "name": "", 113 | "type": "uint256" 114 | } 115 | ], 116 | "stateMutability": "view", 117 | "type": "function" 118 | }, 119 | { 120 | "inputs": [], 121 | "name": "decimals", 122 | "outputs": [ 123 | { 124 | "internalType": "uint8", 125 | "name": "", 126 | "type": "uint8" 127 | } 128 | ], 129 | "stateMutability": "view", 130 | "type": "function" 131 | }, 132 | { 133 | "inputs": [], 134 | "name": "getOwner", 135 | "outputs": [ 136 | { 137 | "internalType": "address", 138 | "name": "", 139 | "type": "address" 140 | } 141 | ], 142 | "stateMutability": "view", 143 | "type": "function" 144 | }, 145 | { 146 | "inputs": [], 147 | "name": "name", 148 | "outputs": [ 149 | { 150 | "internalType": "string", 151 | "name": "", 152 | "type": "string" 153 | } 154 | ], 155 | "stateMutability": "view", 156 | "type": "function" 157 | }, 158 | { 159 | "inputs": [], 160 | "name": "symbol", 161 | "outputs": [ 162 | { 163 | "internalType": "string", 164 | "name": "", 165 | "type": "string" 166 | } 167 | ], 168 | "stateMutability": "view", 169 | "type": "function" 170 | }, 171 | { 172 | "inputs": [], 173 | "name": "totalSupply", 174 | "outputs": [ 175 | { 176 | "internalType": "uint256", 177 | "name": "", 178 | "type": "uint256" 179 | } 180 | ], 181 | "stateMutability": "view", 182 | "type": "function" 183 | }, 184 | { 185 | "inputs": [ 186 | { 187 | "internalType": "address", 188 | "name": "recipient", 189 | "type": "address" 190 | }, 191 | { 192 | "internalType": "uint256", 193 | "name": "amount", 194 | "type": "uint256" 195 | } 196 | ], 197 | "name": "transfer", 198 | "outputs": [ 199 | { 200 | "internalType": "bool", 201 | "name": "", 202 | "type": "bool" 203 | } 204 | ], 205 | "stateMutability": "nonpayable", 206 | "type": "function" 207 | }, 208 | { 209 | "inputs": [ 210 | { 211 | "internalType": "address", 212 | "name": "sender", 213 | "type": "address" 214 | }, 215 | { 216 | "internalType": "address", 217 | "name": "recipient", 218 | "type": "address" 219 | }, 220 | { 221 | "internalType": "uint256", 222 | "name": "amount", 223 | "type": "uint256" 224 | } 225 | ], 226 | "name": "transferFrom", 227 | "outputs": [ 228 | { 229 | "internalType": "bool", 230 | "name": "", 231 | "type": "bool" 232 | } 233 | ], 234 | "stateMutability": "nonpayable", 235 | "type": "function" 236 | } 237 | ]; 238 | -------------------------------------------------------------------------------- /abi/IERC20.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "anonymous": false, 4 | "inputs": [ 5 | { 6 | "indexed": true, 7 | "internalType": "address", 8 | "name": "owner", 9 | "type": "address" 10 | }, 11 | { 12 | "indexed": true, 13 | "internalType": "address", 14 | "name": "spender", 15 | "type": "address" 16 | }, 17 | { 18 | "indexed": false, 19 | "internalType": "uint256", 20 | "name": "value", 21 | "type": "uint256" 22 | } 23 | ], 24 | "name": "Approval", 25 | "type": "event" 26 | }, 27 | { 28 | "anonymous": false, 29 | "inputs": [ 30 | { 31 | "indexed": true, 32 | "internalType": "address", 33 | "name": "from", 34 | "type": "address" 35 | }, 36 | { 37 | "indexed": true, 38 | "internalType": "address", 39 | "name": "to", 40 | "type": "address" 41 | }, 42 | { 43 | "indexed": false, 44 | "internalType": "uint256", 45 | "name": "value", 46 | "type": "uint256" 47 | } 48 | ], 49 | "name": "Transfer", 50 | "type": "event" 51 | }, 52 | { 53 | "inputs": [ 54 | { 55 | "internalType": "address", 56 | "name": "_owner", 57 | "type": "address" 58 | }, 59 | { 60 | "internalType": "address", 61 | "name": "spender", 62 | "type": "address" 63 | } 64 | ], 65 | "name": "allowance", 66 | "outputs": [ 67 | { 68 | "internalType": "uint256", 69 | "name": "", 70 | "type": "uint256" 71 | } 72 | ], 73 | "stateMutability": "view", 74 | "type": "function" 75 | }, 76 | { 77 | "inputs": [ 78 | { 79 | "internalType": "address", 80 | "name": "spender", 81 | "type": "address" 82 | }, 83 | { 84 | "internalType": "uint256", 85 | "name": "amount", 86 | "type": "uint256" 87 | } 88 | ], 89 | "name": "approve", 90 | "outputs": [ 91 | { 92 | "internalType": "bool", 93 | "name": "", 94 | "type": "bool" 95 | } 96 | ], 97 | "stateMutability": "nonpayable", 98 | "type": "function" 99 | }, 100 | { 101 | "inputs": [ 102 | { 103 | "internalType": "address", 104 | "name": "account", 105 | "type": "address" 106 | } 107 | ], 108 | "name": "balanceOf", 109 | "outputs": [ 110 | { 111 | "internalType": "uint256", 112 | "name": "", 113 | "type": "uint256" 114 | } 115 | ], 116 | "stateMutability": "view", 117 | "type": "function" 118 | }, 119 | { 120 | "inputs": [], 121 | "name": "decimals", 122 | "outputs": [ 123 | { 124 | "internalType": "uint8", 125 | "name": "", 126 | "type": "uint8" 127 | } 128 | ], 129 | "stateMutability": "view", 130 | "type": "function" 131 | }, 132 | { 133 | "inputs": [], 134 | "name": "getOwner", 135 | "outputs": [ 136 | { 137 | "internalType": "address", 138 | "name": "", 139 | "type": "address" 140 | } 141 | ], 142 | "stateMutability": "view", 143 | "type": "function" 144 | }, 145 | { 146 | "inputs": [], 147 | "name": "name", 148 | "outputs": [ 149 | { 150 | "internalType": "string", 151 | "name": "", 152 | "type": "string" 153 | } 154 | ], 155 | "stateMutability": "view", 156 | "type": "function" 157 | }, 158 | { 159 | "inputs": [], 160 | "name": "symbol", 161 | "outputs": [ 162 | { 163 | "internalType": "string", 164 | "name": "", 165 | "type": "string" 166 | } 167 | ], 168 | "stateMutability": "view", 169 | "type": "function" 170 | }, 171 | { 172 | "inputs": [], 173 | "name": "totalSupply", 174 | "outputs": [ 175 | { 176 | "internalType": "uint256", 177 | "name": "", 178 | "type": "uint256" 179 | } 180 | ], 181 | "stateMutability": "view", 182 | "type": "function" 183 | }, 184 | { 185 | "inputs": [ 186 | { 187 | "internalType": "address", 188 | "name": "recipient", 189 | "type": "address" 190 | }, 191 | { 192 | "internalType": "uint256", 193 | "name": "amount", 194 | "type": "uint256" 195 | } 196 | ], 197 | "name": "transfer", 198 | "outputs": [ 199 | { 200 | "internalType": "bool", 201 | "name": "", 202 | "type": "bool" 203 | } 204 | ], 205 | "stateMutability": "nonpayable", 206 | "type": "function" 207 | }, 208 | { 209 | "inputs": [ 210 | { 211 | "internalType": "address", 212 | "name": "sender", 213 | "type": "address" 214 | }, 215 | { 216 | "internalType": "address", 217 | "name": "recipient", 218 | "type": "address" 219 | }, 220 | { 221 | "internalType": "uint256", 222 | "name": "amount", 223 | "type": "uint256" 224 | } 225 | ], 226 | "name": "transferFrom", 227 | "outputs": [ 228 | { 229 | "internalType": "bool", 230 | "name": "", 231 | "type": "bool" 232 | } 233 | ], 234 | "stateMutability": "nonpayable", 235 | "type": "function" 236 | } 237 | ] 238 | -------------------------------------------------------------------------------- /abi/IParams.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | "inputs": [], 4 | "name": "depositFeesBPS", 5 | "outputs": [ 6 | { 7 | "internalType": "uint8", 8 | "name": "", 9 | "type": "uint8" 10 | } 11 | ], 12 | "stateMutability": "view", 13 | "type": "function" 14 | }, 15 | { 16 | "inputs": [], 17 | "name": "expirationTime", 18 | "outputs": [ 19 | { 20 | "internalType": "uint256", 21 | "name": "", 22 | "type": "uint256" 23 | } 24 | ], 25 | "stateMutability": "view", 26 | "type": "function" 27 | }, 28 | { 29 | "inputs": [], 30 | "name": "loopCount", 31 | "outputs": [ 32 | { 33 | "internalType": "uint8", 34 | "name": "", 35 | "type": "uint8" 36 | } 37 | ], 38 | "stateMutability": "view", 39 | "type": "function" 40 | }, 41 | { 42 | "inputs": [], 43 | "name": "minimumSwapAmountForWBTC", 44 | "outputs": [ 45 | { 46 | "internalType": "uint256", 47 | "name": "", 48 | "type": "uint256" 49 | } 50 | ], 51 | "stateMutability": "view", 52 | "type": "function" 53 | }, 54 | { 55 | "inputs": [], 56 | "name": "nodeRewardsRatio", 57 | "outputs": [ 58 | { 59 | "internalType": "uint8", 60 | "name": "", 61 | "type": "uint8" 62 | } 63 | ], 64 | "stateMutability": "view", 65 | "type": "function" 66 | }, 67 | { 68 | "inputs": [], 69 | "name": "paraswapAddress", 70 | "outputs": [ 71 | { 72 | "internalType": "address", 73 | "name": "", 74 | "type": "address" 75 | } 76 | ], 77 | "stateMutability": "view", 78 | "type": "function" 79 | }, 80 | { 81 | "inputs": [ 82 | { 83 | "internalType": "uint8", 84 | "name": "_depositFeesBPS", 85 | "type": "uint8" 86 | } 87 | ], 88 | "name": "setDepositFeesBPS", 89 | "outputs": [], 90 | "stateMutability": "nonpayable", 91 | "type": "function" 92 | }, 93 | { 94 | "inputs": [ 95 | { 96 | "internalType": "uint256", 97 | "name": "_expirationTime", 98 | "type": "uint256" 99 | } 100 | ], 101 | "name": "setExpirationTime", 102 | "outputs": [], 103 | "stateMutability": "nonpayable", 104 | "type": "function" 105 | }, 106 | { 107 | "inputs": [ 108 | { 109 | "internalType": "uint8", 110 | "name": "_loopCount", 111 | "type": "uint8" 112 | } 113 | ], 114 | "name": "setLoopCount", 115 | "outputs": [], 116 | "stateMutability": "nonpayable", 117 | "type": "function" 118 | }, 119 | { 120 | "inputs": [ 121 | { 122 | "internalType": "uint256", 123 | "name": "_minimumSwapAmountForWBTC", 124 | "type": "uint256" 125 | } 126 | ], 127 | "name": "setMinimumSwapAmountForWBTC", 128 | "outputs": [], 129 | "stateMutability": "nonpayable", 130 | "type": "function" 131 | }, 132 | { 133 | "inputs": [ 134 | { 135 | "internalType": "uint8", 136 | "name": "_nodeRewardsRatio", 137 | "type": "uint8" 138 | } 139 | ], 140 | "name": "setNodeRewardsRatio", 141 | "outputs": [], 142 | "stateMutability": "nonpayable", 143 | "type": "function" 144 | }, 145 | { 146 | "inputs": [ 147 | { 148 | "internalType": "address", 149 | "name": "_paraswapAddress", 150 | "type": "address" 151 | } 152 | ], 153 | "name": "setParaswapAddress", 154 | "outputs": [], 155 | "stateMutability": "nonpayable", 156 | "type": "function" 157 | }, 158 | { 159 | "inputs": [ 160 | { 161 | "internalType": "uint8", 162 | "name": "_withdrawalFeeBPS", 163 | "type": "uint8" 164 | } 165 | ], 166 | "name": "setWithdrawalFeeBPS", 167 | "outputs": [], 168 | "stateMutability": "nonpayable", 169 | "type": "function" 170 | }, 171 | { 172 | "inputs": [], 173 | "name": "withdrawalFeeBPS", 174 | "outputs": [ 175 | { 176 | "internalType": "uint8", 177 | "name": "", 178 | "type": "uint8" 179 | } 180 | ], 181 | "stateMutability": "view", 182 | "type": "function" 183 | } 184 | ]; 185 | -------------------------------------------------------------------------------- /abi/IParams.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [], 4 | "name": "depositFeesBPS", 5 | "outputs": [ 6 | { 7 | "internalType": "uint8", 8 | "name": "", 9 | "type": "uint8" 10 | } 11 | ], 12 | "stateMutability": "view", 13 | "type": "function" 14 | }, 15 | { 16 | "inputs": [], 17 | "name": "expirationTime", 18 | "outputs": [ 19 | { 20 | "internalType": "uint256", 21 | "name": "", 22 | "type": "uint256" 23 | } 24 | ], 25 | "stateMutability": "view", 26 | "type": "function" 27 | }, 28 | { 29 | "inputs": [], 30 | "name": "loopCount", 31 | "outputs": [ 32 | { 33 | "internalType": "uint8", 34 | "name": "", 35 | "type": "uint8" 36 | } 37 | ], 38 | "stateMutability": "view", 39 | "type": "function" 40 | }, 41 | { 42 | "inputs": [], 43 | "name": "minimumSwapAmountForWBTC", 44 | "outputs": [ 45 | { 46 | "internalType": "uint256", 47 | "name": "", 48 | "type": "uint256" 49 | } 50 | ], 51 | "stateMutability": "view", 52 | "type": "function" 53 | }, 54 | { 55 | "inputs": [], 56 | "name": "nodeRewardsRatio", 57 | "outputs": [ 58 | { 59 | "internalType": "uint8", 60 | "name": "", 61 | "type": "uint8" 62 | } 63 | ], 64 | "stateMutability": "view", 65 | "type": "function" 66 | }, 67 | { 68 | "inputs": [], 69 | "name": "paraswapAddress", 70 | "outputs": [ 71 | { 72 | "internalType": "address", 73 | "name": "", 74 | "type": "address" 75 | } 76 | ], 77 | "stateMutability": "view", 78 | "type": "function" 79 | }, 80 | { 81 | "inputs": [ 82 | { 83 | "internalType": "uint8", 84 | "name": "_depositFeesBPS", 85 | "type": "uint8" 86 | } 87 | ], 88 | "name": "setDepositFeesBPS", 89 | "outputs": [], 90 | "stateMutability": "nonpayable", 91 | "type": "function" 92 | }, 93 | { 94 | "inputs": [ 95 | { 96 | "internalType": "uint256", 97 | "name": "_expirationTime", 98 | "type": "uint256" 99 | } 100 | ], 101 | "name": "setExpirationTime", 102 | "outputs": [], 103 | "stateMutability": "nonpayable", 104 | "type": "function" 105 | }, 106 | { 107 | "inputs": [ 108 | { 109 | "internalType": "uint8", 110 | "name": "_loopCount", 111 | "type": "uint8" 112 | } 113 | ], 114 | "name": "setLoopCount", 115 | "outputs": [], 116 | "stateMutability": "nonpayable", 117 | "type": "function" 118 | }, 119 | { 120 | "inputs": [ 121 | { 122 | "internalType": "uint256", 123 | "name": "_minimumSwapAmountForWBTC", 124 | "type": "uint256" 125 | } 126 | ], 127 | "name": "setMinimumSwapAmountForWBTC", 128 | "outputs": [], 129 | "stateMutability": "nonpayable", 130 | "type": "function" 131 | }, 132 | { 133 | "inputs": [ 134 | { 135 | "internalType": "uint8", 136 | "name": "_nodeRewardsRatio", 137 | "type": "uint8" 138 | } 139 | ], 140 | "name": "setNodeRewardsRatio", 141 | "outputs": [], 142 | "stateMutability": "nonpayable", 143 | "type": "function" 144 | }, 145 | { 146 | "inputs": [ 147 | { 148 | "internalType": "address", 149 | "name": "_paraswapAddress", 150 | "type": "address" 151 | } 152 | ], 153 | "name": "setParaswapAddress", 154 | "outputs": [], 155 | "stateMutability": "nonpayable", 156 | "type": "function" 157 | }, 158 | { 159 | "inputs": [ 160 | { 161 | "internalType": "uint8", 162 | "name": "_withdrawalFeeBPS", 163 | "type": "uint8" 164 | } 165 | ], 166 | "name": "setWithdrawalFeeBPS", 167 | "outputs": [], 168 | "stateMutability": "nonpayable", 169 | "type": "function" 170 | }, 171 | { 172 | "inputs": [], 173 | "name": "withdrawalFeeBPS", 174 | "outputs": [ 175 | { 176 | "internalType": "uint8", 177 | "name": "", 178 | "type": "uint8" 179 | } 180 | ], 181 | "stateMutability": "view", 182 | "type": "function" 183 | } 184 | ] 185 | -------------------------------------------------------------------------------- /abi/ISwapRewards.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "address", 6 | "name": "_dest", 7 | "type": "address" 8 | }, 9 | { 10 | "internalType": "address", 11 | "name": "_receiver", 12 | "type": "address" 13 | }, 14 | { 15 | "internalType": "uint256", 16 | "name": "_swapped", 17 | "type": "uint256" 18 | } 19 | ], 20 | "name": "pullRewards", 21 | "outputs": [ 22 | { 23 | "internalType": "bool", 24 | "name": "", 25 | "type": "bool" 26 | } 27 | ], 28 | "stateMutability": "nonpayable", 29 | "type": "function" 30 | }, 31 | { 32 | "inputs": [ 33 | { 34 | "internalType": "address", 35 | "name": "_dest", 36 | "type": "address" 37 | }, 38 | { 39 | "internalType": "address[]", 40 | "name": "_receiver", 41 | "type": "address[]" 42 | }, 43 | { 44 | "internalType": "uint256[]", 45 | "name": "_swapped", 46 | "type": "uint256[]" 47 | } 48 | ], 49 | "name": "pullRewardsMulti", 50 | "outputs": [ 51 | { 52 | "internalType": "bool", 53 | "name": "", 54 | "type": "bool" 55 | } 56 | ], 57 | "stateMutability": "nonpayable", 58 | "type": "function" 59 | }, 60 | { 61 | "inputs": [ 62 | { 63 | "internalType": "uint256", 64 | "name": "_pricePerBTC", 65 | "type": "uint256" 66 | } 67 | ], 68 | "name": "setSWINGBYPrice", 69 | "outputs": [], 70 | "stateMutability": "nonpayable", 71 | "type": "function" 72 | } 73 | ]; 74 | -------------------------------------------------------------------------------- /abi/ISwapRewards.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "address", 6 | "name": "_dest", 7 | "type": "address" 8 | }, 9 | { 10 | "internalType": "address", 11 | "name": "_receiver", 12 | "type": "address" 13 | }, 14 | { 15 | "internalType": "uint256", 16 | "name": "_swapped", 17 | "type": "uint256" 18 | } 19 | ], 20 | "name": "pullRewards", 21 | "outputs": [ 22 | { 23 | "internalType": "bool", 24 | "name": "", 25 | "type": "bool" 26 | } 27 | ], 28 | "stateMutability": "nonpayable", 29 | "type": "function" 30 | }, 31 | { 32 | "inputs": [ 33 | { 34 | "internalType": "address", 35 | "name": "_dest", 36 | "type": "address" 37 | }, 38 | { 39 | "internalType": "address[]", 40 | "name": "_receiver", 41 | "type": "address[]" 42 | }, 43 | { 44 | "internalType": "uint256[]", 45 | "name": "_swapped", 46 | "type": "uint256[]" 47 | } 48 | ], 49 | "name": "pullRewardsMulti", 50 | "outputs": [ 51 | { 52 | "internalType": "bool", 53 | "name": "", 54 | "type": "bool" 55 | } 56 | ], 57 | "stateMutability": "nonpayable", 58 | "type": "function" 59 | }, 60 | { 61 | "inputs": [ 62 | { 63 | "internalType": "uint256", 64 | "name": "_pricePerBTC", 65 | "type": "uint256" 66 | } 67 | ], 68 | "name": "setSWINGBYPrice", 69 | "outputs": [], 70 | "stateMutability": "nonpayable", 71 | "type": "function" 72 | } 73 | ] 74 | -------------------------------------------------------------------------------- /abi/ITokenTransferProxy.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "address", 6 | "name": "user", 7 | "type": "address" 8 | }, 9 | { 10 | "internalType": "uint256", 11 | "name": "tokensToFree", 12 | "type": "uint256" 13 | } 14 | ], 15 | "name": "freeReduxTokens", 16 | "outputs": [], 17 | "stateMutability": "nonpayable", 18 | "type": "function" 19 | }, 20 | { 21 | "inputs": [ 22 | { 23 | "internalType": "address", 24 | "name": "token", 25 | "type": "address" 26 | }, 27 | { 28 | "internalType": "address", 29 | "name": "from", 30 | "type": "address" 31 | }, 32 | { 33 | "internalType": "address", 34 | "name": "to", 35 | "type": "address" 36 | }, 37 | { 38 | "internalType": "uint256", 39 | "name": "amount", 40 | "type": "uint256" 41 | } 42 | ], 43 | "name": "transferFrom", 44 | "outputs": [], 45 | "stateMutability": "nonpayable", 46 | "type": "function" 47 | } 48 | ]; 49 | -------------------------------------------------------------------------------- /abi/ITokenTransferProxy.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "address", 6 | "name": "user", 7 | "type": "address" 8 | }, 9 | { 10 | "internalType": "uint256", 11 | "name": "tokensToFree", 12 | "type": "uint256" 13 | } 14 | ], 15 | "name": "freeReduxTokens", 16 | "outputs": [], 17 | "stateMutability": "nonpayable", 18 | "type": "function" 19 | }, 20 | { 21 | "inputs": [ 22 | { 23 | "internalType": "address", 24 | "name": "token", 25 | "type": "address" 26 | }, 27 | { 28 | "internalType": "address", 29 | "name": "from", 30 | "type": "address" 31 | }, 32 | { 33 | "internalType": "address", 34 | "name": "to", 35 | "type": "address" 36 | }, 37 | { 38 | "internalType": "uint256", 39 | "name": "amount", 40 | "type": "uint256" 41 | } 42 | ], 43 | "name": "transferFrom", 44 | "outputs": [], 45 | "stateMutability": "nonpayable", 46 | "type": "function" 47 | } 48 | ] 49 | -------------------------------------------------------------------------------- /abi/IWETH.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "address", 6 | "name": "spender", 7 | "type": "address" 8 | }, 9 | { 10 | "internalType": "uint256", 11 | "name": "amount", 12 | "type": "uint256" 13 | } 14 | ], 15 | "name": "approve", 16 | "outputs": [ 17 | { 18 | "internalType": "bool", 19 | "name": "", 20 | "type": "bool" 21 | } 22 | ], 23 | "stateMutability": "nonpayable", 24 | "type": "function" 25 | }, 26 | { 27 | "inputs": [], 28 | "name": "deposit", 29 | "outputs": [], 30 | "stateMutability": "payable", 31 | "type": "function" 32 | }, 33 | { 34 | "inputs": [ 35 | { 36 | "internalType": "address", 37 | "name": "to", 38 | "type": "address" 39 | }, 40 | { 41 | "internalType": "uint256", 42 | "name": "value", 43 | "type": "uint256" 44 | } 45 | ], 46 | "name": "transfer", 47 | "outputs": [ 48 | { 49 | "internalType": "bool", 50 | "name": "", 51 | "type": "bool" 52 | } 53 | ], 54 | "stateMutability": "nonpayable", 55 | "type": "function" 56 | }, 57 | { 58 | "inputs": [ 59 | { 60 | "internalType": "uint256", 61 | "name": "", 62 | "type": "uint256" 63 | } 64 | ], 65 | "name": "withdraw", 66 | "outputs": [], 67 | "stateMutability": "nonpayable", 68 | "type": "function" 69 | } 70 | ]; 71 | -------------------------------------------------------------------------------- /abi/IWETH.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "address", 6 | "name": "spender", 7 | "type": "address" 8 | }, 9 | { 10 | "internalType": "uint256", 11 | "name": "amount", 12 | "type": "uint256" 13 | } 14 | ], 15 | "name": "approve", 16 | "outputs": [ 17 | { 18 | "internalType": "bool", 19 | "name": "", 20 | "type": "bool" 21 | } 22 | ], 23 | "stateMutability": "nonpayable", 24 | "type": "function" 25 | }, 26 | { 27 | "inputs": [], 28 | "name": "deposit", 29 | "outputs": [], 30 | "stateMutability": "payable", 31 | "type": "function" 32 | }, 33 | { 34 | "inputs": [ 35 | { 36 | "internalType": "address", 37 | "name": "to", 38 | "type": "address" 39 | }, 40 | { 41 | "internalType": "uint256", 42 | "name": "value", 43 | "type": "uint256" 44 | } 45 | ], 46 | "name": "transfer", 47 | "outputs": [ 48 | { 49 | "internalType": "bool", 50 | "name": "", 51 | "type": "bool" 52 | } 53 | ], 54 | "stateMutability": "nonpayable", 55 | "type": "function" 56 | }, 57 | { 58 | "inputs": [ 59 | { 60 | "internalType": "uint256", 61 | "name": "", 62 | "type": "uint256" 63 | } 64 | ], 65 | "name": "withdraw", 66 | "outputs": [], 67 | "stateMutability": "nonpayable", 68 | "type": "function" 69 | } 70 | ] 71 | -------------------------------------------------------------------------------- /abi/Ownable.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | "anonymous": false, 4 | "inputs": [ 5 | { 6 | "indexed": true, 7 | "internalType": "address", 8 | "name": "previousOwner", 9 | "type": "address" 10 | }, 11 | { 12 | "indexed": true, 13 | "internalType": "address", 14 | "name": "newOwner", 15 | "type": "address" 16 | } 17 | ], 18 | "name": "OwnershipTransferred", 19 | "type": "event" 20 | }, 21 | { 22 | "inputs": [], 23 | "name": "owner", 24 | "outputs": [ 25 | { 26 | "internalType": "address", 27 | "name": "", 28 | "type": "address" 29 | } 30 | ], 31 | "stateMutability": "view", 32 | "type": "function" 33 | }, 34 | { 35 | "inputs": [], 36 | "name": "renounceOwnership", 37 | "outputs": [], 38 | "stateMutability": "nonpayable", 39 | "type": "function" 40 | }, 41 | { 42 | "inputs": [ 43 | { 44 | "internalType": "address", 45 | "name": "newOwner", 46 | "type": "address" 47 | } 48 | ], 49 | "name": "transferOwnership", 50 | "outputs": [], 51 | "stateMutability": "nonpayable", 52 | "type": "function" 53 | } 54 | ]; 55 | -------------------------------------------------------------------------------- /abi/Ownable.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "anonymous": false, 4 | "inputs": [ 5 | { 6 | "indexed": true, 7 | "internalType": "address", 8 | "name": "previousOwner", 9 | "type": "address" 10 | }, 11 | { 12 | "indexed": true, 13 | "internalType": "address", 14 | "name": "newOwner", 15 | "type": "address" 16 | } 17 | ], 18 | "name": "OwnershipTransferred", 19 | "type": "event" 20 | }, 21 | { 22 | "inputs": [], 23 | "name": "owner", 24 | "outputs": [ 25 | { 26 | "internalType": "address", 27 | "name": "", 28 | "type": "address" 29 | } 30 | ], 31 | "stateMutability": "view", 32 | "type": "function" 33 | }, 34 | { 35 | "inputs": [], 36 | "name": "renounceOwnership", 37 | "outputs": [], 38 | "stateMutability": "nonpayable", 39 | "type": "function" 40 | }, 41 | { 42 | "inputs": [ 43 | { 44 | "internalType": "address", 45 | "name": "newOwner", 46 | "type": "address" 47 | } 48 | ], 49 | "name": "transferOwnership", 50 | "outputs": [], 51 | "stateMutability": "nonpayable", 52 | "type": "function" 53 | } 54 | ] 55 | -------------------------------------------------------------------------------- /abi/Params.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | "inputs": [], 4 | "stateMutability": "nonpayable", 5 | "type": "constructor" 6 | }, 7 | { 8 | "anonymous": false, 9 | "inputs": [ 10 | { 11 | "indexed": true, 12 | "internalType": "address", 13 | "name": "previousOwner", 14 | "type": "address" 15 | }, 16 | { 17 | "indexed": true, 18 | "internalType": "address", 19 | "name": "newOwner", 20 | "type": "address" 21 | } 22 | ], 23 | "name": "OwnershipTransferred", 24 | "type": "event" 25 | }, 26 | { 27 | "inputs": [], 28 | "name": "depositFeesBPS", 29 | "outputs": [ 30 | { 31 | "internalType": "uint8", 32 | "name": "", 33 | "type": "uint8" 34 | } 35 | ], 36 | "stateMutability": "view", 37 | "type": "function" 38 | }, 39 | { 40 | "inputs": [], 41 | "name": "expirationTime", 42 | "outputs": [ 43 | { 44 | "internalType": "uint256", 45 | "name": "", 46 | "type": "uint256" 47 | } 48 | ], 49 | "stateMutability": "view", 50 | "type": "function" 51 | }, 52 | { 53 | "inputs": [], 54 | "name": "loopCount", 55 | "outputs": [ 56 | { 57 | "internalType": "uint8", 58 | "name": "", 59 | "type": "uint8" 60 | } 61 | ], 62 | "stateMutability": "view", 63 | "type": "function" 64 | }, 65 | { 66 | "inputs": [], 67 | "name": "minimumSwapAmountForWBTC", 68 | "outputs": [ 69 | { 70 | "internalType": "uint256", 71 | "name": "", 72 | "type": "uint256" 73 | } 74 | ], 75 | "stateMutability": "view", 76 | "type": "function" 77 | }, 78 | { 79 | "inputs": [], 80 | "name": "nodeRewardsRatio", 81 | "outputs": [ 82 | { 83 | "internalType": "uint8", 84 | "name": "", 85 | "type": "uint8" 86 | } 87 | ], 88 | "stateMutability": "view", 89 | "type": "function" 90 | }, 91 | { 92 | "inputs": [], 93 | "name": "owner", 94 | "outputs": [ 95 | { 96 | "internalType": "address", 97 | "name": "", 98 | "type": "address" 99 | } 100 | ], 101 | "stateMutability": "view", 102 | "type": "function" 103 | }, 104 | { 105 | "inputs": [], 106 | "name": "paraswapAddress", 107 | "outputs": [ 108 | { 109 | "internalType": "address", 110 | "name": "", 111 | "type": "address" 112 | } 113 | ], 114 | "stateMutability": "view", 115 | "type": "function" 116 | }, 117 | { 118 | "inputs": [], 119 | "name": "renounceOwnership", 120 | "outputs": [], 121 | "stateMutability": "nonpayable", 122 | "type": "function" 123 | }, 124 | { 125 | "inputs": [ 126 | { 127 | "internalType": "uint8", 128 | "name": "_depositFeesBPS", 129 | "type": "uint8" 130 | } 131 | ], 132 | "name": "setDepositFeesBPS", 133 | "outputs": [], 134 | "stateMutability": "nonpayable", 135 | "type": "function" 136 | }, 137 | { 138 | "inputs": [ 139 | { 140 | "internalType": "uint256", 141 | "name": "_expirationTime", 142 | "type": "uint256" 143 | } 144 | ], 145 | "name": "setExpirationTime", 146 | "outputs": [], 147 | "stateMutability": "nonpayable", 148 | "type": "function" 149 | }, 150 | { 151 | "inputs": [ 152 | { 153 | "internalType": "uint8", 154 | "name": "_loopCount", 155 | "type": "uint8" 156 | } 157 | ], 158 | "name": "setLoopCount", 159 | "outputs": [], 160 | "stateMutability": "nonpayable", 161 | "type": "function" 162 | }, 163 | { 164 | "inputs": [ 165 | { 166 | "internalType": "uint256", 167 | "name": "_minimumSwapAmountForWBTC", 168 | "type": "uint256" 169 | } 170 | ], 171 | "name": "setMinimumSwapAmountForWBTC", 172 | "outputs": [], 173 | "stateMutability": "nonpayable", 174 | "type": "function" 175 | }, 176 | { 177 | "inputs": [ 178 | { 179 | "internalType": "uint8", 180 | "name": "_nodeRewardsRatio", 181 | "type": "uint8" 182 | } 183 | ], 184 | "name": "setNodeRewardsRatio", 185 | "outputs": [], 186 | "stateMutability": "nonpayable", 187 | "type": "function" 188 | }, 189 | { 190 | "inputs": [ 191 | { 192 | "internalType": "address", 193 | "name": "_paraswapAddress", 194 | "type": "address" 195 | } 196 | ], 197 | "name": "setParaswapAddress", 198 | "outputs": [], 199 | "stateMutability": "nonpayable", 200 | "type": "function" 201 | }, 202 | { 203 | "inputs": [ 204 | { 205 | "internalType": "uint8", 206 | "name": "_withdrawalFeeBPS", 207 | "type": "uint8" 208 | } 209 | ], 210 | "name": "setWithdrawalFeeBPS", 211 | "outputs": [], 212 | "stateMutability": "nonpayable", 213 | "type": "function" 214 | }, 215 | { 216 | "inputs": [ 217 | { 218 | "internalType": "address", 219 | "name": "newOwner", 220 | "type": "address" 221 | } 222 | ], 223 | "name": "transferOwnership", 224 | "outputs": [], 225 | "stateMutability": "nonpayable", 226 | "type": "function" 227 | }, 228 | { 229 | "inputs": [], 230 | "name": "withdrawalFeeBPS", 231 | "outputs": [ 232 | { 233 | "internalType": "uint8", 234 | "name": "", 235 | "type": "uint8" 236 | } 237 | ], 238 | "stateMutability": "view", 239 | "type": "function" 240 | } 241 | ]; 242 | -------------------------------------------------------------------------------- /abi/Params.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [], 4 | "stateMutability": "nonpayable", 5 | "type": "constructor" 6 | }, 7 | { 8 | "anonymous": false, 9 | "inputs": [ 10 | { 11 | "indexed": true, 12 | "internalType": "address", 13 | "name": "previousOwner", 14 | "type": "address" 15 | }, 16 | { 17 | "indexed": true, 18 | "internalType": "address", 19 | "name": "newOwner", 20 | "type": "address" 21 | } 22 | ], 23 | "name": "OwnershipTransferred", 24 | "type": "event" 25 | }, 26 | { 27 | "inputs": [], 28 | "name": "depositFeesBPS", 29 | "outputs": [ 30 | { 31 | "internalType": "uint8", 32 | "name": "", 33 | "type": "uint8" 34 | } 35 | ], 36 | "stateMutability": "view", 37 | "type": "function" 38 | }, 39 | { 40 | "inputs": [], 41 | "name": "expirationTime", 42 | "outputs": [ 43 | { 44 | "internalType": "uint256", 45 | "name": "", 46 | "type": "uint256" 47 | } 48 | ], 49 | "stateMutability": "view", 50 | "type": "function" 51 | }, 52 | { 53 | "inputs": [], 54 | "name": "loopCount", 55 | "outputs": [ 56 | { 57 | "internalType": "uint8", 58 | "name": "", 59 | "type": "uint8" 60 | } 61 | ], 62 | "stateMutability": "view", 63 | "type": "function" 64 | }, 65 | { 66 | "inputs": [], 67 | "name": "minimumSwapAmountForWBTC", 68 | "outputs": [ 69 | { 70 | "internalType": "uint256", 71 | "name": "", 72 | "type": "uint256" 73 | } 74 | ], 75 | "stateMutability": "view", 76 | "type": "function" 77 | }, 78 | { 79 | "inputs": [], 80 | "name": "nodeRewardsRatio", 81 | "outputs": [ 82 | { 83 | "internalType": "uint8", 84 | "name": "", 85 | "type": "uint8" 86 | } 87 | ], 88 | "stateMutability": "view", 89 | "type": "function" 90 | }, 91 | { 92 | "inputs": [], 93 | "name": "owner", 94 | "outputs": [ 95 | { 96 | "internalType": "address", 97 | "name": "", 98 | "type": "address" 99 | } 100 | ], 101 | "stateMutability": "view", 102 | "type": "function" 103 | }, 104 | { 105 | "inputs": [], 106 | "name": "paraswapAddress", 107 | "outputs": [ 108 | { 109 | "internalType": "address", 110 | "name": "", 111 | "type": "address" 112 | } 113 | ], 114 | "stateMutability": "view", 115 | "type": "function" 116 | }, 117 | { 118 | "inputs": [], 119 | "name": "renounceOwnership", 120 | "outputs": [], 121 | "stateMutability": "nonpayable", 122 | "type": "function" 123 | }, 124 | { 125 | "inputs": [ 126 | { 127 | "internalType": "uint8", 128 | "name": "_depositFeesBPS", 129 | "type": "uint8" 130 | } 131 | ], 132 | "name": "setDepositFeesBPS", 133 | "outputs": [], 134 | "stateMutability": "nonpayable", 135 | "type": "function" 136 | }, 137 | { 138 | "inputs": [ 139 | { 140 | "internalType": "uint256", 141 | "name": "_expirationTime", 142 | "type": "uint256" 143 | } 144 | ], 145 | "name": "setExpirationTime", 146 | "outputs": [], 147 | "stateMutability": "nonpayable", 148 | "type": "function" 149 | }, 150 | { 151 | "inputs": [ 152 | { 153 | "internalType": "uint8", 154 | "name": "_loopCount", 155 | "type": "uint8" 156 | } 157 | ], 158 | "name": "setLoopCount", 159 | "outputs": [], 160 | "stateMutability": "nonpayable", 161 | "type": "function" 162 | }, 163 | { 164 | "inputs": [ 165 | { 166 | "internalType": "uint256", 167 | "name": "_minimumSwapAmountForWBTC", 168 | "type": "uint256" 169 | } 170 | ], 171 | "name": "setMinimumSwapAmountForWBTC", 172 | "outputs": [], 173 | "stateMutability": "nonpayable", 174 | "type": "function" 175 | }, 176 | { 177 | "inputs": [ 178 | { 179 | "internalType": "uint8", 180 | "name": "_nodeRewardsRatio", 181 | "type": "uint8" 182 | } 183 | ], 184 | "name": "setNodeRewardsRatio", 185 | "outputs": [], 186 | "stateMutability": "nonpayable", 187 | "type": "function" 188 | }, 189 | { 190 | "inputs": [ 191 | { 192 | "internalType": "address", 193 | "name": "_paraswapAddress", 194 | "type": "address" 195 | } 196 | ], 197 | "name": "setParaswapAddress", 198 | "outputs": [], 199 | "stateMutability": "nonpayable", 200 | "type": "function" 201 | }, 202 | { 203 | "inputs": [ 204 | { 205 | "internalType": "uint8", 206 | "name": "_withdrawalFeeBPS", 207 | "type": "uint8" 208 | } 209 | ], 210 | "name": "setWithdrawalFeeBPS", 211 | "outputs": [], 212 | "stateMutability": "nonpayable", 213 | "type": "function" 214 | }, 215 | { 216 | "inputs": [ 217 | { 218 | "internalType": "address", 219 | "name": "newOwner", 220 | "type": "address" 221 | } 222 | ], 223 | "name": "transferOwnership", 224 | "outputs": [], 225 | "stateMutability": "nonpayable", 226 | "type": "function" 227 | }, 228 | { 229 | "inputs": [], 230 | "name": "withdrawalFeeBPS", 231 | "outputs": [ 232 | { 233 | "internalType": "uint8", 234 | "name": "", 235 | "type": "uint8" 236 | } 237 | ], 238 | "stateMutability": "view", 239 | "type": "function" 240 | } 241 | ] 242 | -------------------------------------------------------------------------------- /abi/SwapRewards.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "address", 6 | "name": "_owner", 7 | "type": "address" 8 | }, 9 | { 10 | "internalType": "address", 11 | "name": "_swingby", 12 | "type": "address" 13 | }, 14 | { 15 | "internalType": "uint256", 16 | "name": "_pricePerBTC", 17 | "type": "uint256" 18 | } 19 | ], 20 | "stateMutability": "nonpayable", 21 | "type": "constructor" 22 | }, 23 | { 24 | "anonymous": false, 25 | "inputs": [ 26 | { 27 | "indexed": true, 28 | "internalType": "address", 29 | "name": "previousOwner", 30 | "type": "address" 31 | }, 32 | { 33 | "indexed": true, 34 | "internalType": "address", 35 | "name": "newOwner", 36 | "type": "address" 37 | } 38 | ], 39 | "name": "OwnershipTransferred", 40 | "type": "event" 41 | }, 42 | { 43 | "anonymous": false, 44 | "inputs": [ 45 | { 46 | "indexed": false, 47 | "internalType": "address", 48 | "name": "to", 49 | "type": "address" 50 | }, 51 | { 52 | "indexed": false, 53 | "internalType": "uint256", 54 | "name": "amount", 55 | "type": "uint256" 56 | }, 57 | { 58 | "indexed": false, 59 | "internalType": "uint256", 60 | "name": "rebate", 61 | "type": "uint256" 62 | } 63 | ], 64 | "name": "Paid", 65 | "type": "event" 66 | }, 67 | { 68 | "inputs": [], 69 | "name": "owner", 70 | "outputs": [ 71 | { 72 | "internalType": "address", 73 | "name": "", 74 | "type": "address" 75 | } 76 | ], 77 | "stateMutability": "view", 78 | "type": "function" 79 | }, 80 | { 81 | "inputs": [], 82 | "name": "pricePerBTC", 83 | "outputs": [ 84 | { 85 | "internalType": "uint256", 86 | "name": "", 87 | "type": "uint256" 88 | } 89 | ], 90 | "stateMutability": "view", 91 | "type": "function" 92 | }, 93 | { 94 | "inputs": [ 95 | { 96 | "internalType": "address", 97 | "name": "_dest", 98 | "type": "address" 99 | }, 100 | { 101 | "internalType": "address", 102 | "name": "_receiver", 103 | "type": "address" 104 | }, 105 | { 106 | "internalType": "uint256", 107 | "name": "_swapped", 108 | "type": "uint256" 109 | } 110 | ], 111 | "name": "pullRewards", 112 | "outputs": [ 113 | { 114 | "internalType": "bool", 115 | "name": "", 116 | "type": "bool" 117 | } 118 | ], 119 | "stateMutability": "nonpayable", 120 | "type": "function" 121 | }, 122 | { 123 | "inputs": [ 124 | { 125 | "internalType": "address", 126 | "name": "_dest", 127 | "type": "address" 128 | }, 129 | { 130 | "internalType": "address[]", 131 | "name": "_receiver", 132 | "type": "address[]" 133 | }, 134 | { 135 | "internalType": "uint256[]", 136 | "name": "_swapped", 137 | "type": "uint256[]" 138 | } 139 | ], 140 | "name": "pullRewardsMulti", 141 | "outputs": [ 142 | { 143 | "internalType": "bool", 144 | "name": "", 145 | "type": "bool" 146 | } 147 | ], 148 | "stateMutability": "nonpayable", 149 | "type": "function" 150 | }, 151 | { 152 | "inputs": [], 153 | "name": "rebateRate", 154 | "outputs": [ 155 | { 156 | "internalType": "uint256", 157 | "name": "", 158 | "type": "uint256" 159 | } 160 | ], 161 | "stateMutability": "view", 162 | "type": "function" 163 | }, 164 | { 165 | "inputs": [], 166 | "name": "renounceOwnership", 167 | "outputs": [], 168 | "stateMutability": "nonpayable", 169 | "type": "function" 170 | }, 171 | { 172 | "inputs": [], 173 | "name": "rewardToken", 174 | "outputs": [ 175 | { 176 | "internalType": "contract IERC20", 177 | "name": "", 178 | "type": "address" 179 | } 180 | ], 181 | "stateMutability": "view", 182 | "type": "function" 183 | }, 184 | { 185 | "inputs": [ 186 | { 187 | "internalType": "uint256", 188 | "name": "_pricePerBTC", 189 | "type": "uint256" 190 | } 191 | ], 192 | "name": "setSWINGBYPrice", 193 | "outputs": [], 194 | "stateMutability": "nonpayable", 195 | "type": "function" 196 | }, 197 | { 198 | "inputs": [ 199 | { 200 | "internalType": "address", 201 | "name": "_swap", 202 | "type": "address" 203 | }, 204 | { 205 | "internalType": "uint256", 206 | "name": "_newRebateRate", 207 | "type": "uint256" 208 | }, 209 | { 210 | "internalType": "uint256", 211 | "name": "_thresholdRatio", 212 | "type": "uint256" 213 | } 214 | ], 215 | "name": "setSwap", 216 | "outputs": [], 217 | "stateMutability": "nonpayable", 218 | "type": "function" 219 | }, 220 | { 221 | "inputs": [], 222 | "name": "swapContract", 223 | "outputs": [ 224 | { 225 | "internalType": "contract ISwapContract", 226 | "name": "", 227 | "type": "address" 228 | } 229 | ], 230 | "stateMutability": "view", 231 | "type": "function" 232 | }, 233 | { 234 | "inputs": [], 235 | "name": "thresholdRatio", 236 | "outputs": [ 237 | { 238 | "internalType": "uint256", 239 | "name": "", 240 | "type": "uint256" 241 | } 242 | ], 243 | "stateMutability": "view", 244 | "type": "function" 245 | }, 246 | { 247 | "inputs": [ 248 | { 249 | "internalType": "address", 250 | "name": "newOwner", 251 | "type": "address" 252 | } 253 | ], 254 | "name": "transferOwnership", 255 | "outputs": [], 256 | "stateMutability": "nonpayable", 257 | "type": "function" 258 | } 259 | ]; 260 | -------------------------------------------------------------------------------- /abi/SwapRewards.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "address", 6 | "name": "_owner", 7 | "type": "address" 8 | }, 9 | { 10 | "internalType": "address", 11 | "name": "_swingby", 12 | "type": "address" 13 | }, 14 | { 15 | "internalType": "uint256", 16 | "name": "_pricePerBTC", 17 | "type": "uint256" 18 | } 19 | ], 20 | "stateMutability": "nonpayable", 21 | "type": "constructor" 22 | }, 23 | { 24 | "anonymous": false, 25 | "inputs": [ 26 | { 27 | "indexed": true, 28 | "internalType": "address", 29 | "name": "previousOwner", 30 | "type": "address" 31 | }, 32 | { 33 | "indexed": true, 34 | "internalType": "address", 35 | "name": "newOwner", 36 | "type": "address" 37 | } 38 | ], 39 | "name": "OwnershipTransferred", 40 | "type": "event" 41 | }, 42 | { 43 | "anonymous": false, 44 | "inputs": [ 45 | { 46 | "indexed": false, 47 | "internalType": "address", 48 | "name": "to", 49 | "type": "address" 50 | }, 51 | { 52 | "indexed": false, 53 | "internalType": "uint256", 54 | "name": "amount", 55 | "type": "uint256" 56 | }, 57 | { 58 | "indexed": false, 59 | "internalType": "uint256", 60 | "name": "rebate", 61 | "type": "uint256" 62 | } 63 | ], 64 | "name": "Paid", 65 | "type": "event" 66 | }, 67 | { 68 | "inputs": [], 69 | "name": "owner", 70 | "outputs": [ 71 | { 72 | "internalType": "address", 73 | "name": "", 74 | "type": "address" 75 | } 76 | ], 77 | "stateMutability": "view", 78 | "type": "function" 79 | }, 80 | { 81 | "inputs": [], 82 | "name": "pricePerBTC", 83 | "outputs": [ 84 | { 85 | "internalType": "uint256", 86 | "name": "", 87 | "type": "uint256" 88 | } 89 | ], 90 | "stateMutability": "view", 91 | "type": "function" 92 | }, 93 | { 94 | "inputs": [ 95 | { 96 | "internalType": "address", 97 | "name": "_dest", 98 | "type": "address" 99 | }, 100 | { 101 | "internalType": "address", 102 | "name": "_receiver", 103 | "type": "address" 104 | }, 105 | { 106 | "internalType": "uint256", 107 | "name": "_swapped", 108 | "type": "uint256" 109 | } 110 | ], 111 | "name": "pullRewards", 112 | "outputs": [ 113 | { 114 | "internalType": "bool", 115 | "name": "", 116 | "type": "bool" 117 | } 118 | ], 119 | "stateMutability": "nonpayable", 120 | "type": "function" 121 | }, 122 | { 123 | "inputs": [ 124 | { 125 | "internalType": "address", 126 | "name": "_dest", 127 | "type": "address" 128 | }, 129 | { 130 | "internalType": "address[]", 131 | "name": "_receiver", 132 | "type": "address[]" 133 | }, 134 | { 135 | "internalType": "uint256[]", 136 | "name": "_swapped", 137 | "type": "uint256[]" 138 | } 139 | ], 140 | "name": "pullRewardsMulti", 141 | "outputs": [ 142 | { 143 | "internalType": "bool", 144 | "name": "", 145 | "type": "bool" 146 | } 147 | ], 148 | "stateMutability": "nonpayable", 149 | "type": "function" 150 | }, 151 | { 152 | "inputs": [], 153 | "name": "rebateRate", 154 | "outputs": [ 155 | { 156 | "internalType": "uint256", 157 | "name": "", 158 | "type": "uint256" 159 | } 160 | ], 161 | "stateMutability": "view", 162 | "type": "function" 163 | }, 164 | { 165 | "inputs": [], 166 | "name": "renounceOwnership", 167 | "outputs": [], 168 | "stateMutability": "nonpayable", 169 | "type": "function" 170 | }, 171 | { 172 | "inputs": [], 173 | "name": "rewardToken", 174 | "outputs": [ 175 | { 176 | "internalType": "contract IERC20", 177 | "name": "", 178 | "type": "address" 179 | } 180 | ], 181 | "stateMutability": "view", 182 | "type": "function" 183 | }, 184 | { 185 | "inputs": [ 186 | { 187 | "internalType": "uint256", 188 | "name": "_pricePerBTC", 189 | "type": "uint256" 190 | } 191 | ], 192 | "name": "setSWINGBYPrice", 193 | "outputs": [], 194 | "stateMutability": "nonpayable", 195 | "type": "function" 196 | }, 197 | { 198 | "inputs": [ 199 | { 200 | "internalType": "address", 201 | "name": "_swap", 202 | "type": "address" 203 | }, 204 | { 205 | "internalType": "uint256", 206 | "name": "_newRebateRate", 207 | "type": "uint256" 208 | }, 209 | { 210 | "internalType": "uint256", 211 | "name": "_thresholdRatio", 212 | "type": "uint256" 213 | } 214 | ], 215 | "name": "setSwap", 216 | "outputs": [], 217 | "stateMutability": "nonpayable", 218 | "type": "function" 219 | }, 220 | { 221 | "inputs": [], 222 | "name": "swapContract", 223 | "outputs": [ 224 | { 225 | "internalType": "contract ISwapContract", 226 | "name": "", 227 | "type": "address" 228 | } 229 | ], 230 | "stateMutability": "view", 231 | "type": "function" 232 | }, 233 | { 234 | "inputs": [], 235 | "name": "thresholdRatio", 236 | "outputs": [ 237 | { 238 | "internalType": "uint256", 239 | "name": "", 240 | "type": "uint256" 241 | } 242 | ], 243 | "stateMutability": "view", 244 | "type": "function" 245 | }, 246 | { 247 | "inputs": [ 248 | { 249 | "internalType": "address", 250 | "name": "newOwner", 251 | "type": "address" 252 | } 253 | ], 254 | "name": "transferOwnership", 255 | "outputs": [], 256 | "stateMutability": "nonpayable", 257 | "type": "function" 258 | } 259 | ] 260 | -------------------------------------------------------------------------------- /abi/sbBTCPool.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | "anonymous": false, 4 | "inputs": [ 5 | { 6 | "indexed": true, 7 | "internalType": "address", 8 | "name": "user", 9 | "type": "address" 10 | }, 11 | { 12 | "indexed": false, 13 | "internalType": "uint256", 14 | "name": "amount", 15 | "type": "uint256" 16 | } 17 | ], 18 | "name": "Claim", 19 | "type": "event" 20 | }, 21 | { 22 | "anonymous": false, 23 | "inputs": [ 24 | { 25 | "indexed": true, 26 | "internalType": "address", 27 | "name": "previousOwner", 28 | "type": "address" 29 | }, 30 | { 31 | "indexed": true, 32 | "internalType": "address", 33 | "name": "newOwner", 34 | "type": "address" 35 | } 36 | ], 37 | "name": "OwnershipTransferred", 38 | "type": "event" 39 | }, 40 | { 41 | "inputs": [], 42 | "name": "ackFunds", 43 | "outputs": [], 44 | "stateMutability": "nonpayable", 45 | "type": "function" 46 | }, 47 | { 48 | "inputs": [], 49 | "name": "balanceBefore", 50 | "outputs": [ 51 | { 52 | "internalType": "uint256", 53 | "name": "", 54 | "type": "uint256" 55 | } 56 | ], 57 | "stateMutability": "view", 58 | "type": "function" 59 | }, 60 | { 61 | "inputs": [], 62 | "name": "barn", 63 | "outputs": [ 64 | { 65 | "internalType": "contract IBarn", 66 | "name": "", 67 | "type": "address" 68 | } 69 | ], 70 | "stateMutability": "view", 71 | "type": "function" 72 | }, 73 | { 74 | "inputs": [], 75 | "name": "claim", 76 | "outputs": [ 77 | { 78 | "internalType": "uint256", 79 | "name": "", 80 | "type": "uint256" 81 | } 82 | ], 83 | "stateMutability": "nonpayable", 84 | "type": "function" 85 | }, 86 | { 87 | "inputs": [], 88 | "name": "currentMultiplier", 89 | "outputs": [ 90 | { 91 | "internalType": "uint256", 92 | "name": "", 93 | "type": "uint256" 94 | } 95 | ], 96 | "stateMutability": "view", 97 | "type": "function" 98 | }, 99 | { 100 | "inputs": [], 101 | "name": "emergencyWithdraw", 102 | "outputs": [], 103 | "stateMutability": "nonpayable", 104 | "type": "function" 105 | }, 106 | { 107 | "inputs": [ 108 | { 109 | "internalType": "address", 110 | "name": "", 111 | "type": "address" 112 | } 113 | ], 114 | "name": "owed", 115 | "outputs": [ 116 | { 117 | "internalType": "uint256", 118 | "name": "", 119 | "type": "uint256" 120 | } 121 | ], 122 | "stateMutability": "view", 123 | "type": "function" 124 | }, 125 | { 126 | "inputs": [], 127 | "name": "owner", 128 | "outputs": [ 129 | { 130 | "internalType": "address", 131 | "name": "", 132 | "type": "address" 133 | } 134 | ], 135 | "stateMutability": "view", 136 | "type": "function" 137 | }, 138 | { 139 | "inputs": [], 140 | "name": "renounceOwnership", 141 | "outputs": [], 142 | "stateMutability": "nonpayable", 143 | "type": "function" 144 | }, 145 | { 146 | "inputs": [ 147 | { 148 | "internalType": "address", 149 | "name": "_node", 150 | "type": "address" 151 | } 152 | ], 153 | "name": "resetUnstakedNode", 154 | "outputs": [], 155 | "stateMutability": "nonpayable", 156 | "type": "function" 157 | }, 158 | { 159 | "inputs": [], 160 | "name": "rewardToken", 161 | "outputs": [ 162 | { 163 | "internalType": "contract IERC20", 164 | "name": "", 165 | "type": "address" 166 | } 167 | ], 168 | "stateMutability": "view", 169 | "type": "function" 170 | }, 171 | { 172 | "inputs": [ 173 | { 174 | "internalType": "address", 175 | "name": "_barn", 176 | "type": "address" 177 | }, 178 | { 179 | "internalType": "address", 180 | "name": "_swap", 181 | "type": "address" 182 | } 183 | ], 184 | "name": "setBarnAndSwap", 185 | "outputs": [], 186 | "stateMutability": "nonpayable", 187 | "type": "function" 188 | }, 189 | { 190 | "inputs": [], 191 | "name": "swapContract", 192 | "outputs": [ 193 | { 194 | "internalType": "contract ISwapContract", 195 | "name": "", 196 | "type": "address" 197 | } 198 | ], 199 | "stateMutability": "view", 200 | "type": "function" 201 | }, 202 | { 203 | "inputs": [], 204 | "name": "totalNodeStaked", 205 | "outputs": [ 206 | { 207 | "internalType": "uint256", 208 | "name": "", 209 | "type": "uint256" 210 | } 211 | ], 212 | "stateMutability": "view", 213 | "type": "function" 214 | }, 215 | { 216 | "inputs": [ 217 | { 218 | "internalType": "address", 219 | "name": "newOwner", 220 | "type": "address" 221 | } 222 | ], 223 | "name": "transferOwnership", 224 | "outputs": [], 225 | "stateMutability": "nonpayable", 226 | "type": "function" 227 | }, 228 | { 229 | "inputs": [ 230 | { 231 | "internalType": "uint256", 232 | "name": "_timestamp", 233 | "type": "uint256" 234 | } 235 | ], 236 | "name": "updateAll", 237 | "outputs": [], 238 | "stateMutability": "nonpayable", 239 | "type": "function" 240 | }, 241 | { 242 | "inputs": [ 243 | { 244 | "internalType": "address", 245 | "name": "", 246 | "type": "address" 247 | } 248 | ], 249 | "name": "userMultiplier", 250 | "outputs": [ 251 | { 252 | "internalType": "uint256", 253 | "name": "", 254 | "type": "uint256" 255 | } 256 | ], 257 | "stateMutability": "view", 258 | "type": "function" 259 | } 260 | ]; 261 | -------------------------------------------------------------------------------- /abi/sbBTCPool.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "anonymous": false, 4 | "inputs": [ 5 | { 6 | "indexed": true, 7 | "internalType": "address", 8 | "name": "user", 9 | "type": "address" 10 | }, 11 | { 12 | "indexed": false, 13 | "internalType": "uint256", 14 | "name": "amount", 15 | "type": "uint256" 16 | } 17 | ], 18 | "name": "Claim", 19 | "type": "event" 20 | }, 21 | { 22 | "anonymous": false, 23 | "inputs": [ 24 | { 25 | "indexed": true, 26 | "internalType": "address", 27 | "name": "previousOwner", 28 | "type": "address" 29 | }, 30 | { 31 | "indexed": true, 32 | "internalType": "address", 33 | "name": "newOwner", 34 | "type": "address" 35 | } 36 | ], 37 | "name": "OwnershipTransferred", 38 | "type": "event" 39 | }, 40 | { 41 | "inputs": [], 42 | "name": "ackFunds", 43 | "outputs": [], 44 | "stateMutability": "nonpayable", 45 | "type": "function" 46 | }, 47 | { 48 | "inputs": [], 49 | "name": "balanceBefore", 50 | "outputs": [ 51 | { 52 | "internalType": "uint256", 53 | "name": "", 54 | "type": "uint256" 55 | } 56 | ], 57 | "stateMutability": "view", 58 | "type": "function" 59 | }, 60 | { 61 | "inputs": [], 62 | "name": "barn", 63 | "outputs": [ 64 | { 65 | "internalType": "contract IBarn", 66 | "name": "", 67 | "type": "address" 68 | } 69 | ], 70 | "stateMutability": "view", 71 | "type": "function" 72 | }, 73 | { 74 | "inputs": [], 75 | "name": "claim", 76 | "outputs": [ 77 | { 78 | "internalType": "uint256", 79 | "name": "", 80 | "type": "uint256" 81 | } 82 | ], 83 | "stateMutability": "nonpayable", 84 | "type": "function" 85 | }, 86 | { 87 | "inputs": [], 88 | "name": "currentMultiplier", 89 | "outputs": [ 90 | { 91 | "internalType": "uint256", 92 | "name": "", 93 | "type": "uint256" 94 | } 95 | ], 96 | "stateMutability": "view", 97 | "type": "function" 98 | }, 99 | { 100 | "inputs": [], 101 | "name": "emergencyWithdraw", 102 | "outputs": [], 103 | "stateMutability": "nonpayable", 104 | "type": "function" 105 | }, 106 | { 107 | "inputs": [ 108 | { 109 | "internalType": "address", 110 | "name": "", 111 | "type": "address" 112 | } 113 | ], 114 | "name": "owed", 115 | "outputs": [ 116 | { 117 | "internalType": "uint256", 118 | "name": "", 119 | "type": "uint256" 120 | } 121 | ], 122 | "stateMutability": "view", 123 | "type": "function" 124 | }, 125 | { 126 | "inputs": [], 127 | "name": "owner", 128 | "outputs": [ 129 | { 130 | "internalType": "address", 131 | "name": "", 132 | "type": "address" 133 | } 134 | ], 135 | "stateMutability": "view", 136 | "type": "function" 137 | }, 138 | { 139 | "inputs": [], 140 | "name": "renounceOwnership", 141 | "outputs": [], 142 | "stateMutability": "nonpayable", 143 | "type": "function" 144 | }, 145 | { 146 | "inputs": [ 147 | { 148 | "internalType": "address", 149 | "name": "_node", 150 | "type": "address" 151 | } 152 | ], 153 | "name": "resetUnstakedNode", 154 | "outputs": [], 155 | "stateMutability": "nonpayable", 156 | "type": "function" 157 | }, 158 | { 159 | "inputs": [], 160 | "name": "rewardToken", 161 | "outputs": [ 162 | { 163 | "internalType": "contract IERC20", 164 | "name": "", 165 | "type": "address" 166 | } 167 | ], 168 | "stateMutability": "view", 169 | "type": "function" 170 | }, 171 | { 172 | "inputs": [ 173 | { 174 | "internalType": "address", 175 | "name": "_barn", 176 | "type": "address" 177 | }, 178 | { 179 | "internalType": "address", 180 | "name": "_swap", 181 | "type": "address" 182 | } 183 | ], 184 | "name": "setBarnAndSwap", 185 | "outputs": [], 186 | "stateMutability": "nonpayable", 187 | "type": "function" 188 | }, 189 | { 190 | "inputs": [], 191 | "name": "swapContract", 192 | "outputs": [ 193 | { 194 | "internalType": "contract ISwapContract", 195 | "name": "", 196 | "type": "address" 197 | } 198 | ], 199 | "stateMutability": "view", 200 | "type": "function" 201 | }, 202 | { 203 | "inputs": [], 204 | "name": "totalNodeStaked", 205 | "outputs": [ 206 | { 207 | "internalType": "uint256", 208 | "name": "", 209 | "type": "uint256" 210 | } 211 | ], 212 | "stateMutability": "view", 213 | "type": "function" 214 | }, 215 | { 216 | "inputs": [ 217 | { 218 | "internalType": "address", 219 | "name": "newOwner", 220 | "type": "address" 221 | } 222 | ], 223 | "name": "transferOwnership", 224 | "outputs": [], 225 | "stateMutability": "nonpayable", 226 | "type": "function" 227 | }, 228 | { 229 | "inputs": [ 230 | { 231 | "internalType": "uint256", 232 | "name": "_timestamp", 233 | "type": "uint256" 234 | } 235 | ], 236 | "name": "updateAll", 237 | "outputs": [], 238 | "stateMutability": "nonpayable", 239 | "type": "function" 240 | }, 241 | { 242 | "inputs": [ 243 | { 244 | "internalType": "address", 245 | "name": "", 246 | "type": "address" 247 | } 248 | ], 249 | "name": "userMultiplier", 250 | "outputs": [ 251 | { 252 | "internalType": "uint256", 253 | "name": "", 254 | "type": "uint256" 255 | } 256 | ], 257 | "stateMutability": "view", 258 | "type": "function" 259 | } 260 | ] 261 | -------------------------------------------------------------------------------- /args.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | "0xde6bD5afCDCCA4dD5DA8e3904345Ed02dC735374", 3 | "0xaD6D458402F60fD3Bd25163575031ACDce07538D", 4 | "0xc778417e063141139fce010982780140aa0cd5ab", 5 | 0 6 | ] -------------------------------------------------------------------------------- /contracts/LPToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0 2 | pragma solidity ^0.8.0; 3 | 4 | import "./BurnableToken.sol"; 5 | 6 | contract LPToken is BurnableToken { 7 | address public old; 8 | 9 | constructor(uint8 _decimals) { 10 | _initialize("Swingby BTC LP Token", "sbBTC", _decimals, 0, true); 11 | } 12 | 13 | function setOld(address _old) public onlyOwner { 14 | old = _old; 15 | } 16 | 17 | /// @dev convertTo allows to convert new LPT when user burnd this tokens at the same time. 18 | /// note: new LPT has to allow minting permission from this contract. 19 | function convertTo(LPToken target, uint256 amount) public { 20 | require(address(target) != address(this), "target != this contract"); 21 | _burn(_msgSender(), amount); 22 | target.mintFrom(_msgSender(), amount); 23 | } 24 | 25 | function mintFrom(address target, uint256 amount) public returns (bool) { 26 | require(old != address(this), "target != this contract"); 27 | require(msg.sender == old, "caller is not old"); 28 | _mint(target, amount); 29 | return true; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /contracts/Params.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0 2 | pragma solidity ^0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | import "./interfaces/IParams.sol"; 5 | import "@openzeppelin/contracts/access/Ownable.sol"; 6 | 7 | contract Params is Ownable, IParams { 8 | uint256 public minimumSwapAmountForWBTC; 9 | uint256 public expirationTime; 10 | address public paraswapAddress; 11 | uint8 public nodeRewardsRatio; 12 | uint8 public depositFeesBPS; 13 | uint8 public withdrawalFeeBPS; 14 | uint8 public loopCount; //max loops when cleaning up expired SkyPools TXs 15 | 16 | constructor() { 17 | //Initialize minimumSwapAmountForWBTC 18 | minimumSwapAmountForWBTC = 24000; 19 | // Initialize expirationTime 20 | expirationTime = 172800; //2 days 21 | // Initialize paraswap address to current address 22 | paraswapAddress = 0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57; 23 | // Initialize nodeRewardsRatio 24 | nodeRewardsRatio = 66; 25 | // Initialize withdrawalFeeBPS 26 | withdrawalFeeBPS = 20; 27 | // Initialize depositFeesBPS 28 | depositFeesBPS = 0; 29 | // Initialize loopCount 30 | loopCount = 10; 31 | } 32 | 33 | function setMinimumSwapAmountForWBTC(uint256 _minimumSwapAmountForWBTC) 34 | external 35 | onlyOwner 36 | { 37 | require( 38 | _minimumSwapAmountForWBTC > 0, 39 | "_minimumSwapAmountForWBTC can not be 0" 40 | ); 41 | minimumSwapAmountForWBTC = _minimumSwapAmountForWBTC; 42 | } 43 | 44 | function setExpirationTime(uint256 _expirationTime) external onlyOwner { 45 | require(_expirationTime >= 0, "_expirationTime can not be 0"); 46 | expirationTime = _expirationTime; 47 | } 48 | 49 | function setParaswapAddress(address _paraswapAddress) external onlyOwner { 50 | paraswapAddress = _paraswapAddress; 51 | } 52 | 53 | function setNodeRewardsRatio(uint8 _nodeRewardsRatio) external onlyOwner { 54 | require( 55 | _nodeRewardsRatio >= 0 && _nodeRewardsRatio <= 100, 56 | "_nodeRewardsRatio is not valid" 57 | ); 58 | nodeRewardsRatio = _nodeRewardsRatio; 59 | } 60 | 61 | function setWithdrawalFeeBPS(uint8 _withdrawalFeeBPS) external onlyOwner { 62 | require( 63 | _withdrawalFeeBPS >= 0 && _withdrawalFeeBPS <= 100, 64 | "_withdrawalFeeBPS is invalid" 65 | ); 66 | withdrawalFeeBPS = _withdrawalFeeBPS; 67 | } 68 | 69 | function setDepositFeesBPS(uint8 _depositFeesBPS) external onlyOwner { 70 | require( 71 | _depositFeesBPS >= 0 && _depositFeesBPS <= 100, 72 | "_depositFeesBPS is invalid" 73 | ); 74 | depositFeesBPS = _depositFeesBPS; 75 | } 76 | 77 | function setLoopCount(uint8 _loopCount) external onlyOwner { 78 | require(_loopCount != 0, "_loopCount can not equal 0"); 79 | loopCount = _loopCount; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /contracts/SwapRewards.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | pragma solidity ^0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | import "@openzeppelin/contracts/access/Ownable.sol"; 6 | import "@openzeppelin/contracts/utils/math/SafeMath.sol"; 7 | import "./interfaces/ISwapContract.sol"; 8 | 9 | contract SwapRewards is Ownable { 10 | using SafeMath for uint256; 11 | 12 | IERC20 public immutable rewardToken; //swingby 13 | ISwapContract public swapContract; 14 | uint256 public rebateRate = 30; // BPS base 15 | uint256 public thresholdRatio = 55; // diff is over 10% 16 | uint256 public pricePerBTC; 17 | 18 | event Paid(address to, uint256 amount, uint256 rebate); 19 | 20 | constructor( 21 | address _owner, 22 | address _swingby, 23 | uint256 _pricePerBTC 24 | ) { 25 | require(_owner != address(0), "owner address is not be 0x0"); 26 | require(_swingby != address(0), "swingby address must not be 0x0"); 27 | 28 | transferOwnership(_owner); 29 | rewardToken = IERC20(_swingby); 30 | pricePerBTC = _pricePerBTC; 31 | } 32 | 33 | // expected DAO executes this 34 | function setSWINGBYPrice(uint256 _pricePerBTC) external { 35 | require(msg.sender == owner(), "!owner"); 36 | pricePerBTC = _pricePerBTC; 37 | } 38 | 39 | function setSwap( 40 | address _swap, 41 | uint256 _newRebateRate, 42 | uint256 _thresholdRatio 43 | ) external { 44 | require(msg.sender == owner(), "!owner"); 45 | require( 46 | _newRebateRate >= 0 && _newRebateRate <= 100, 47 | "_newRebateRate is not valid" 48 | ); 49 | require( 50 | _thresholdRatio >= 20 && _thresholdRatio <= 100, 51 | "_thresholdRatio is not valid" 52 | ); 53 | swapContract = ISwapContract(_swap); 54 | rebateRate = _newRebateRate; 55 | thresholdRatio = _thresholdRatio; 56 | } 57 | 58 | // pullRewards transfers the funds to the user 59 | function pullRewards( 60 | address _dest, 61 | address _receiver, 62 | uint256 _swapped 63 | ) external returns (bool) { 64 | require( 65 | msg.sender == address(swapContract), 66 | "caller is not swap contact" 67 | ); 68 | address tokenB = swapContract.BTCT_ADDR(); 69 | (uint256 balA, uint256 balB) = swapContract.getFloatReserve( 70 | address(0), 71 | tokenB 72 | ); 73 | uint256 threshold = balA.add(balB).mul(thresholdRatio).div(100); 74 | if ( 75 | (_dest == tokenB && balB >= threshold) || 76 | (_dest == address(0) && balA >= threshold) 77 | ) { 78 | uint256 amount = _swapped.mul(rebateRate).mul(pricePerBTC).mul(1e6); 79 | rewardToken.transfer(_receiver, amount); // decimals == 18 for payout 80 | emit Paid(_receiver, _swapped, amount); 81 | } 82 | return true; 83 | } 84 | 85 | // pullRewardsMulti transfers the funds to the user 86 | function pullRewardsMulti( 87 | address _dest, 88 | address[] memory _receiver, 89 | uint256[] memory _swapped 90 | ) external returns (bool) { 91 | require( 92 | msg.sender == address(swapContract), 93 | "caller is not swap contact" 94 | ); 95 | require(_receiver.length == _swapped.length, "array size is not match"); 96 | address tokenB = swapContract.BTCT_ADDR(); 97 | (uint256 balA, uint256 balB) = swapContract.getFloatReserve( 98 | address(0), 99 | tokenB 100 | ); 101 | uint256 threshold = balA.add(balB).mul(thresholdRatio).div(100); 102 | if ( 103 | (_dest == tokenB && balB >= threshold) || 104 | (_dest == address(0) && balA >= threshold) 105 | ) { 106 | for (uint256 i = 0; i < _receiver.length; i++) { 107 | uint256 amount = _swapped[i] 108 | .mul(rebateRate) 109 | .mul(pricePerBTC) 110 | .mul(1e6); 111 | rewardToken.transfer(_receiver[i], amount); // decimals == 18 for payout 112 | emit Paid(_receiver[i], _swapped[i], amount); 113 | } 114 | } 115 | return true; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /contracts/SwingbyToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0 2 | pragma solidity ^0.8.0; 3 | 4 | import "./BurnableToken.sol"; 5 | 6 | contract SwingbyToken is BurnableToken { 7 | constructor() { 8 | _initialize("SWINGBY token", "SWINGBY", 18, 0, true); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /contracts/interfaces/IAugustusSwapper.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0 2 | pragma solidity ^0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | import "./IERC20.sol"; 6 | 7 | interface IAugustusSwapper { 8 | 9 | /** 10 | * @param fromToken Address of the source token 11 | * @param fromAmount Amount of source tokens to be swapped 12 | * @param toAmount Minimum destination token amount expected out of this swap 13 | * @param expectedAmount Expected amount of destination tokens without slippage 14 | * @param beneficiary Beneficiary address 15 | * 0 then 100% will be transferred to beneficiary. Pass 10000 for 100% 16 | * @param referrer referral id 17 | * @param useReduxToken whether to use redux token or not 18 | * @param path Route to be taken for this swap to take place 19 | 20 | */ 21 | struct SellData { 22 | address fromToken; 23 | uint256 fromAmount; 24 | uint256 toAmount; 25 | uint256 expectedAmount; 26 | address payable beneficiary; 27 | string referrer; 28 | bool useReduxToken; 29 | Path[] path; 30 | 31 | } 32 | 33 | struct MegaSwapSellData { 34 | address fromToken; 35 | uint256 fromAmount; 36 | uint256 toAmount; 37 | uint256 expectedAmount; 38 | address payable beneficiary; 39 | string referrer; 40 | bool useReduxToken; 41 | MegaSwapPath[] path; 42 | } 43 | 44 | struct BuyData { 45 | address fromToken; 46 | address toToken; 47 | uint256 fromAmount; 48 | uint256 toAmount; 49 | address payable beneficiary; 50 | string referrer; 51 | bool useReduxToken; 52 | BuyRoute[] route; 53 | } 54 | 55 | struct Route { 56 | address payable exchange; 57 | address targetExchange; 58 | uint percent; 59 | bytes payload; 60 | uint256 networkFee;//Network fee is associated with 0xv3 trades 61 | } 62 | 63 | struct MegaSwapPath { 64 | uint256 fromAmountPercent; 65 | Path[] path; 66 | } 67 | 68 | struct Path { 69 | address to; 70 | uint256 totalNetworkFee;//Network fee is associated with 0xv3 trades 71 | Route[] routes; 72 | } 73 | 74 | struct BuyRoute { 75 | address payable exchange; 76 | address targetExchange; 77 | uint256 fromAmount; 78 | uint256 toAmount; 79 | bytes payload; 80 | uint256 networkFee;//Network fee is associated with 0xv3 trades 81 | } 82 | 83 | function getPartnerRegistry() external view returns(address); 84 | 85 | function getWhitelistAddress() external view returns(address); 86 | 87 | function getFeeWallet() external view returns(address); 88 | 89 | function getTokenTransferProxy() external view returns (address); 90 | 91 | function getUniswapProxy() external view returns(address); 92 | 93 | function getVersion() external view returns(string memory); 94 | 95 | /** 96 | * @dev The function which performs the multi path swap. 97 | */ 98 | function multiSwap( 99 | SellData calldata data 100 | ) 101 | external 102 | payable 103 | returns (uint256); 104 | 105 | /** 106 | * @dev The function which performs the single path buy. 107 | */ 108 | function buy( 109 | BuyData calldata data 110 | ) 111 | external 112 | payable 113 | returns (uint256); 114 | 115 | function swapOnUniswap( 116 | uint256 amountIn, 117 | uint256 amountOutMin, 118 | address[] calldata path, 119 | uint8 referrer 120 | ) 121 | external 122 | payable; 123 | 124 | function buyOnUniswap( 125 | uint256 amountInMax, 126 | uint256 amountOut, 127 | address[] calldata path, 128 | uint8 referrer 129 | ) 130 | external 131 | payable; 132 | 133 | function buyOnUniswapFork( 134 | address factory, 135 | bytes32 initCode, 136 | uint256 amountInMax, 137 | uint256 amountOut, 138 | address[] calldata path, 139 | uint8 referrer 140 | ) 141 | external 142 | payable; 143 | 144 | function swapOnUniswapFork( 145 | address factory, 146 | bytes32 initCode, 147 | uint256 amountIn, 148 | uint256 amountOutMin, 149 | address[] calldata path, 150 | uint8 referrer 151 | ) 152 | external 153 | payable; 154 | 155 | 156 | function simplBuy( 157 | address fromToken, 158 | address toToken, 159 | uint256 fromAmount, 160 | uint256 toAmount, 161 | address[] memory callees, 162 | bytes memory exchangeData, 163 | uint256[] memory startIndexes, 164 | uint256[] memory values, 165 | address payable beneficiary, 166 | string memory referrer, 167 | bool useReduxToken 168 | ) 169 | external 170 | payable; 171 | 172 | function simpleSwap( 173 | address fromToken, 174 | address toToken, 175 | uint256 fromAmount, 176 | uint256 toAmount, 177 | uint256 expectedAmount, 178 | address[] memory callees, 179 | bytes memory exchangeData, 180 | uint256[] memory startIndexes, 181 | uint256[] memory values, 182 | address payable beneficiary, 183 | string memory referrer, 184 | bool useReduxToken 185 | ) 186 | external 187 | payable 188 | returns (uint256 receivedAmount); 189 | 190 | /** 191 | * @dev The function which performs the mega path swap. 192 | * @param data Data required to perform swap. 193 | */ 194 | function megaSwap( 195 | MegaSwapSellData memory data 196 | ) 197 | external 198 | payable 199 | returns (uint256); 200 | } -------------------------------------------------------------------------------- /contracts/interfaces/IBarn.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | pragma solidity ^0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | interface IBarn { 6 | // balanceOf returns the current BOND balance of a user (bonus not included) 7 | function balanceOf(address user) external view returns (uint256); 8 | 9 | // balanceAtTs returns the amount of BOND that the user currently staked (bonus NOT included) 10 | function balanceAtTs( 11 | address user, 12 | uint256 timestamp 13 | ) external view returns (uint256); 14 | } 15 | -------------------------------------------------------------------------------- /contracts/interfaces/IBurnableToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0 2 | pragma solidity ^0.8.0; 3 | 4 | import "./IERC20.sol"; 5 | 6 | interface IBurnableToken is IERC20 { 7 | function mint(address target, uint256 amount) external returns (bool); 8 | 9 | function burn(uint256 amount) external returns (bool); 10 | 11 | function mintable() external returns (bool); 12 | } 13 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0 2 | pragma solidity ^0.8.0; 3 | 4 | interface IERC20 { 5 | /** 6 | * @dev Returns the amount of tokens in existence. 7 | */ 8 | function totalSupply() external view returns (uint256); 9 | 10 | /** 11 | * @dev Returns the token decimals. 12 | */ 13 | function decimals() external view returns (uint8); 14 | 15 | /** 16 | * @dev Returns the token symbol. 17 | */ 18 | function symbol() external view returns (string memory); 19 | 20 | /** 21 | * @dev Returns the token name. 22 | */ 23 | function name() external view returns (string memory); 24 | 25 | /** 26 | * @dev Returns the bep token owner. (This is a BEP-20 token specific.) 27 | */ 28 | function getOwner() external view returns (address); 29 | 30 | /** 31 | * @dev Returns the amount of tokens owned by `account`. 32 | */ 33 | function balanceOf(address account) external view returns (uint256); 34 | 35 | /** 36 | * @dev Moves `amount` tokens from the caller's account to `recipient`. 37 | * 38 | * Returns a boolean value indicating whether the operation succeeded. 39 | * 40 | * Emits a {Transfer} event. 41 | */ 42 | function transfer(address recipient, uint256 amount) 43 | external 44 | returns (bool); 45 | 46 | /** 47 | * @dev Returns the remaining number of tokens that `spender` will be 48 | * allowed to spend on behalf of `owner` through {transferFrom}. This is 49 | * zero by default. 50 | * 51 | * This value changes when {approve} or {transferFrom} are called. 52 | */ 53 | function allowance(address _owner, address spender) 54 | external 55 | view 56 | returns (uint256); 57 | 58 | /** 59 | * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 60 | * 61 | * Returns a boolean value indicating whether the operation succeeded. 62 | * 63 | * IMPORTANT: Beware that changing an allowance with this method brings the risk 64 | * that someone may use both the old and the new allowance by unfortunate 65 | * transaction ordering. One possible solution to mitigate this race 66 | * condition is to first reduce the spender's allowance to 0 and set the 67 | * desired value afterwards: 68 | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 69 | * 70 | * Emits an {Approval} event. 71 | */ 72 | function approve(address spender, uint256 amount) external returns (bool); 73 | 74 | /** 75 | * @dev Moves `amount` tokens from `sender` to `recipient` using the 76 | * allowance mechanism. `amount` is then deducted from the caller's 77 | * allowance. 78 | * 79 | * Returns a boolean value indicating whether the operation succeeded. 80 | * 81 | * Emits a {Transfer} event. 82 | */ 83 | function transferFrom( 84 | address sender, 85 | address recipient, 86 | uint256 amount 87 | ) external returns (bool); 88 | 89 | /** 90 | * @dev Emitted when `value` tokens are moved from one account (`from`) to 91 | * another (`to`). 92 | * 93 | * Note that `value` may be zero. 94 | */ 95 | event Transfer(address indexed from, address indexed to, uint256 value); 96 | 97 | /** 98 | * @dev Emitted when the allowance of a `spender` for an `owner` is set by 99 | * a call to {approve}. `value` is the new allowance. 100 | */ 101 | event Approval( 102 | address indexed owner, 103 | address indexed spender, 104 | uint256 value 105 | ); 106 | } 107 | -------------------------------------------------------------------------------- /contracts/interfaces/IParams.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0 2 | pragma solidity ^0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | interface IParams { 6 | 7 | function minimumSwapAmountForWBTC() external view returns (uint256); 8 | function expirationTime() external view returns (uint256); 9 | function paraswapAddress() external view returns (address); 10 | function nodeRewardsRatio() external view returns (uint8); 11 | function depositFeesBPS() external view returns (uint8); 12 | function withdrawalFeeBPS() external view returns (uint8); 13 | function loopCount() external view returns (uint8); 14 | 15 | function setMinimumSwapAmountForWBTC(uint256 _minimumSwapAmountForWBTC) external; 16 | 17 | function setExpirationTime(uint256 _expirationTime) external; 18 | 19 | function setParaswapAddress(address _paraswapAddress) external; 20 | 21 | function setNodeRewardsRatio(uint8 _nodeRewardsRatio) external; 22 | 23 | function setWithdrawalFeeBPS(uint8 _withdrawalFeeBPS) external; 24 | 25 | function setDepositFeesBPS(uint8 _depositFeesBPS) external; 26 | 27 | function setLoopCount(uint8 _loopCount) external; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /contracts/interfaces/IParaswap.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0 2 | 3 | pragma solidity ^0.8.0; 4 | pragma experimental ABIEncoderV2; 5 | 6 | import "./lib/Utils.sol"; 7 | import "./IERC20.sol"; 8 | 9 | interface IParaswap { 10 | function multiSwap( 11 | Utils.SellData calldata data 12 | ) external payable returns (uint256); 13 | 14 | function megaSwap( 15 | Utils.MegaSwapSellData calldata data 16 | ) external payable returns (uint256); 17 | 18 | function protectedMultiSwap( 19 | Utils.SellData calldata data 20 | ) external payable returns (uint256); 21 | 22 | function protectedMegaSwap( 23 | Utils.MegaSwapSellData calldata data 24 | ) external payable returns (uint256); 25 | 26 | function protectedSimpleSwap( 27 | Utils.SimpleData calldata data 28 | ) external payable returns (uint256 receivedAmount); 29 | 30 | function protectedSimpleBuy( 31 | Utils.SimpleData calldata data 32 | ) external payable; 33 | 34 | function simpleSwap( 35 | Utils.SimpleData calldata data 36 | ) external payable returns (uint256 receivedAmount); 37 | 38 | function simpleBuy(Utils.SimpleData calldata data) external payable; 39 | 40 | function swapOnUniswap( 41 | uint256 amountIn, 42 | uint256 amountOutMin, 43 | address[] calldata path 44 | ) external payable; 45 | 46 | function swapOnUniswapFork( 47 | address factory, 48 | bytes32 initCode, 49 | uint256 amountIn, 50 | uint256 amountOutMin, 51 | address[] calldata path 52 | ) external payable; 53 | 54 | function buyOnUniswap( 55 | uint256 amountInMax, 56 | uint256 amountOut, 57 | address[] calldata path 58 | ) external payable; 59 | 60 | function buyOnUniswapFork( 61 | address factory, 62 | bytes32 initCode, 63 | uint256 amountInMax, 64 | uint256 amountOut, 65 | address[] calldata path 66 | ) external payable; 67 | 68 | function swapOnUniswapV2Fork( 69 | address tokenIn, 70 | uint256 amountIn, 71 | uint256 amountOutMin, 72 | address weth, 73 | uint256[] calldata pools 74 | ) external payable; 75 | 76 | function buyOnUniswapV2Fork( 77 | address tokenIn, 78 | uint256 amountInMax, 79 | uint256 amountOut, 80 | address weth, 81 | uint256[] calldata pools 82 | ) external payable; 83 | 84 | function swapOnZeroXv2( 85 | IERC20 fromToken, 86 | IERC20 toToken, 87 | uint256 fromAmount, 88 | uint256 amountOutMin, 89 | address exchange, 90 | bytes calldata payload 91 | ) external payable; 92 | 93 | function swapOnZeroXv4( 94 | IERC20 fromToken, 95 | IERC20 toToken, 96 | uint256 fromAmount, 97 | uint256 amountOutMin, 98 | address exchange, 99 | bytes calldata payload 100 | ) external payable; 101 | } 102 | -------------------------------------------------------------------------------- /contracts/interfaces/ISwapContract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0 2 | pragma solidity ^0.8.0; 3 | pragma experimental ABIEncoderV2; 4 | 5 | import "./IBurnableToken.sol"; 6 | 7 | interface ISwapContract { 8 | function BTCT_ADDR() external returns (address); 9 | 10 | function lpToken() external returns (IBurnableToken); 11 | 12 | function singleTransferERC20( 13 | address _destToken, 14 | address _to, 15 | uint256 _amount, 16 | uint256 _totalSwapped, 17 | uint256 _rewardsAmount, 18 | bytes32[] memory _redeemedFloatTxIds 19 | ) external returns (bool); 20 | 21 | function multiTransferERC20TightlyPacked( 22 | address _destToken, 23 | bytes32[] memory _addressesAndAmounts, 24 | uint256 _totalSwapped, 25 | uint256 _rewardsAmount, 26 | bytes32[] memory _redeemedFloatTxIds 27 | ) external returns (bool); 28 | 29 | function collectSwapFeesForBTC( 30 | uint256 _incomingAmount, 31 | uint256 _minerFee, 32 | uint256 _rewardsAmount, 33 | address[] memory _spenders, 34 | uint256[] memory _swapAmounts 35 | ) external returns (bool); 36 | 37 | function recordIncomingFloat( 38 | address _token, 39 | bytes32 _addressesAndAmountOfFloat, 40 | bytes32 _txid 41 | ) external returns (bool); 42 | 43 | function recordOutcomingFloat( 44 | address _token, 45 | bytes32 _addressesAndAmountOfLPtoken, 46 | uint256 _minerFee, 47 | bytes32 _txid 48 | ) external returns (bool); 49 | 50 | function recordUTXOSweepMinerFee( 51 | uint256 _minerFee, 52 | bytes32 _txid 53 | ) external returns (bool); 54 | 55 | function churn( 56 | address _newOwner, 57 | address[] memory _nodes, 58 | bool[] memory _isRemoved, 59 | uint8 _churnedInCount, 60 | uint8 _tssThreshold 61 | ) external returns (bool); 62 | 63 | function updateParams( 64 | address _sbBTCPool, 65 | address _buybackAddress, 66 | uint256 _withdrawalFeeBPS, 67 | uint256 _nodeRewardsRatio, 68 | uint256 _buybackRewardsRatio 69 | ) external returns (bool); 70 | 71 | function isTxUsed(bytes32 _txid) external view returns (bool); 72 | 73 | function getCurrentPriceLP() external view returns (uint256); 74 | 75 | function getFloatReserve( 76 | address _tokenA, 77 | address _tokenB 78 | ) external returns (uint256 reserveA, uint256 reserveB); 79 | 80 | function getActiveNodes() external view returns (address[] memory); 81 | 82 | function isNodeStake(address _user) external returns (bool); 83 | } 84 | -------------------------------------------------------------------------------- /contracts/interfaces/ISwapRewards.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0 2 | pragma solidity ^0.8.0; 3 | 4 | interface ISwapRewards { 5 | 6 | function setSWINGBYPrice(uint256 _pricePerBTC) external; 7 | 8 | function pullRewards(address _dest, address _receiver, uint256 _swapped) external returns (bool); 9 | 10 | function pullRewardsMulti(address _dest, address[] memory _receiver, uint256[] memory _swapped) external returns (bool); 11 | } 12 | -------------------------------------------------------------------------------- /contracts/interfaces/ITokenTransferProxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | 6 | interface ITokenTransferProxy { 7 | 8 | function transferFrom( 9 | address token, 10 | address from, 11 | address to, 12 | uint256 amount 13 | ) 14 | external; 15 | 16 | function freeReduxTokens(address user, uint256 tokensToFree) external; 17 | } -------------------------------------------------------------------------------- /contracts/interfaces/IWETH.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | interface IWETH { 6 | function deposit() external payable; 7 | 8 | function transfer(address to, uint256 value) external returns (bool); 9 | 10 | function withdraw(uint256) external; 11 | 12 | function approve(address spender, uint256 amount) external returns (bool); 13 | } 14 | -------------------------------------------------------------------------------- /contracts/interfaces/lib/SafeERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "../IERC20.sol"; 6 | import "./Address.sol"; 7 | 8 | /** 9 | * @title SafeERC20 10 | * @dev Wrappers around ERC20 operations that throw on failure (when the token 11 | * contract returns false). Tokens that return no value (and instead revert or 12 | * throw on failure) are also supported, non-reverting calls are assumed to be 13 | * successful. 14 | * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 15 | * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 16 | */ 17 | library SafeERC20 { 18 | using Address for address; 19 | 20 | function safeTransfer( 21 | IERC20 token, 22 | address to, 23 | uint256 value 24 | ) internal { 25 | _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 26 | } 27 | 28 | function safeTransferFrom( 29 | IERC20 token, 30 | address from, 31 | address to, 32 | uint256 value 33 | ) internal { 34 | _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 35 | } 36 | 37 | /** 38 | * @dev Deprecated. This function has issues similar to the ones found in 39 | * {IERC20-approve}, and its usage is discouraged. 40 | * 41 | * Whenever possible, use {safeIncreaseAllowance} and 42 | * {safeDecreaseAllowance} instead. 43 | */ 44 | function safeApprove( 45 | IERC20 token, 46 | address spender, 47 | uint256 value 48 | ) internal { 49 | // safeApprove should only be called when setting an initial allowance, 50 | // or when resetting it to zero. To increase and decrease it, use 51 | // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 52 | require( 53 | (value == 0) || (token.allowance(address(this), spender) == 0), 54 | "SafeERC20: approve from non-zero to non-zero allowance" 55 | ); 56 | _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 57 | } 58 | 59 | function safeIncreaseAllowance( 60 | IERC20 token, 61 | address spender, 62 | uint256 value 63 | ) internal { 64 | uint256 newAllowance = token.allowance(address(this), spender) + value; 65 | _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 66 | } 67 | 68 | 69 | 70 | /** 71 | * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 72 | * on the return value: the return value is optional (but if data is returned, it must not be false). 73 | * @param token The token targeted by the call. 74 | * @param data The call data (encoded using abi.encode or one of its variants). 75 | */ 76 | function _callOptionalReturn(IERC20 token, bytes memory data) private { 77 | // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 78 | // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 79 | // the target address contains contract code and also asserts for success in the low-level call. 80 | 81 | bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); 82 | if (returndata.length > 0) { 83 | // Return data is optional 84 | require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /contracts/interfaces/lib/Utils.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | library Utils { 6 | /** 7 | * @param fromToken Address of the source token 8 | * @param fromAmount Amount of source tokens to be swapped 9 | * @param toAmount Minimum destination token amount expected out of this swap 10 | * @param expectedAmount Expected amount of destination tokens without slippage 11 | * @param beneficiary Beneficiary address 12 | * 0 then 100% will be transferred to beneficiary. Pass 10000 for 100% 13 | * @param path Route to be taken for this swap to take place 14 | 15 | */ 16 | struct SellData { 17 | address fromToken; 18 | uint256 fromAmount; 19 | uint256 toAmount; 20 | uint256 expectedAmount; 21 | address payable beneficiary; 22 | Utils.Path[] path; 23 | address payable partner; 24 | uint256 feePercent; 25 | bytes permit; 26 | uint256 deadline; 27 | bytes16 uuid; 28 | } 29 | 30 | struct MegaSwapSellData { 31 | address fromToken; 32 | uint256 fromAmount; 33 | uint256 toAmount; 34 | uint256 expectedAmount; 35 | address payable beneficiary; 36 | Utils.MegaSwapPath[] path; 37 | address payable partner; 38 | uint256 feePercent; 39 | bytes permit; 40 | uint256 deadline; 41 | bytes16 uuid; 42 | } 43 | 44 | struct SimpleData { 45 | address fromToken; 46 | address toToken; 47 | uint256 fromAmount; 48 | uint256 toAmount; 49 | uint256 expectedAmount; 50 | address[] callees; 51 | bytes exchangeData; 52 | uint256[] startIndexes; 53 | uint256[] values; 54 | address payable beneficiary; 55 | address payable partner; 56 | uint256 feePercent; 57 | bytes permit; 58 | uint256 deadline; 59 | bytes16 uuid; 60 | } 61 | 62 | struct Adapter { 63 | address payable adapter; 64 | uint256 percent; 65 | uint256 networkFee; 66 | Route[] route; 67 | } 68 | 69 | struct Route { 70 | uint256 index;//Adapter at which index needs to be used 71 | address targetExchange; 72 | uint percent; 73 | bytes payload; 74 | uint256 networkFee;//Network fee is associated with 0xv3 trades 75 | } 76 | 77 | struct MegaSwapPath { 78 | uint256 fromAmountPercent; 79 | Path[] path; 80 | } 81 | 82 | struct Path { 83 | address to; 84 | uint256 totalNetworkFee;//Network fee is associated with 0xv3 trades 85 | Adapter[] adapters; 86 | } 87 | } -------------------------------------------------------------------------------- /contracts/sbBTCPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | pragma solidity ^0.8.0; 3 | 4 | import "@openzeppelin/contracts/access/Ownable.sol"; 5 | import "@openzeppelin/contracts/utils/math/SafeMath.sol"; 6 | import "./interfaces/IBarn.sol"; 7 | import "./interfaces/ISwapContract.sol"; 8 | 9 | contract sbBTCPool is Ownable { 10 | using SafeMath for uint256; 11 | 12 | uint256 constant divisor = 10 ** 27; 13 | 14 | uint256 public balanceBefore; 15 | uint256 public currentMultiplier; 16 | uint256 public totalNodeStaked; 17 | 18 | mapping(address => uint256) public userMultiplier; 19 | mapping(address => uint256) public owed; 20 | 21 | IBarn public barn; 22 | IERC20 public rewardToken; 23 | ISwapContract public swapContract; 24 | 25 | event Claim(address indexed user, uint256 amount); 26 | 27 | // setBarn sets the address of the BarnBridge Barn into the state variable 28 | function setBarnAndSwap(address _barn, address _swap) public { 29 | require(_barn != address(0), "barn address must not be 0x0"); 30 | require(_swap != address(0), "swap contract address must not be 0x0"); 31 | require(msg.sender == owner(), "!owner"); 32 | swapContract = ISwapContract(_swap); 33 | rewardToken = IERC20(swapContract.lpToken()); 34 | barn = IBarn(_barn); 35 | } 36 | 37 | // update all node rewards. 38 | function updateAll(uint256 _timestamp) public onlyOwner { 39 | updateStakes(_timestamp); 40 | // Getting rewards 41 | ackFunds(); 42 | // Update all distribution. 43 | address[] memory nodes = swapContract.getActiveNodes(); 44 | for (uint256 i = 0; i < nodes.length; i++) { 45 | _updateOwed(nodes[i], _timestamp); 46 | } 47 | } 48 | 49 | // check all active nodes to calculate current stakes. 50 | function updateStakes(uint256 _timestamp) internal { 51 | address[] memory nodes = swapContract.getActiveNodes(); 52 | uint256 newTotalNodeStaked; 53 | for (uint256 i = 0; i < nodes.length; i++) { 54 | newTotalNodeStaked = newTotalNodeStaked.add( 55 | barn.balanceAtTs(nodes[i], _timestamp) 56 | ); 57 | if (userMultiplier[nodes[i]] == 0) { 58 | userMultiplier[nodes[i]] = currentMultiplier; 59 | } 60 | } 61 | // only change when stakers had actions. 62 | if (totalNodeStaked != newTotalNodeStaked) { 63 | totalNodeStaked = newTotalNodeStaked; 64 | } 65 | } 66 | 67 | function resetUnstakedNode(address _node) public { 68 | require(!swapContract.isNodeStake(_node), "node is staker"); 69 | userMultiplier[_node] = 0; 70 | } 71 | 72 | // claim calculates the currently owed reward and transfers the funds to the user 73 | function claim() public returns (uint256) { 74 | require(swapContract.isNodeStake(msg.sender), "caller is not node"); 75 | 76 | updateStakes(block.timestamp); 77 | 78 | ackFunds(); 79 | 80 | _updateOwed(msg.sender, block.timestamp); 81 | 82 | uint256 amount = owed[msg.sender]; 83 | require(amount > 0, "nothing to claim"); 84 | 85 | owed[msg.sender] = 0; 86 | 87 | rewardToken.transfer(msg.sender, amount); 88 | 89 | // acknowledge the amount that was transferred to the user 90 | ackFunds(); 91 | 92 | emit Claim(msg.sender, amount); 93 | 94 | return amount; 95 | } 96 | 97 | // ackFunds checks the difference between the last known balance of `token` and the current one 98 | // if it goes up, the multiplier is re-calculated 99 | // if it goes down, it only updates the known balance 100 | function ackFunds() public { 101 | uint256 balanceNow = rewardToken.balanceOf(address(this)); 102 | 103 | if (balanceNow == 0 || balanceNow <= balanceBefore) { 104 | balanceBefore = balanceNow; 105 | return; 106 | } 107 | if (totalNodeStaked == 0) { 108 | return; 109 | } 110 | 111 | uint256 diff = balanceNow.sub(balanceBefore); 112 | uint256 multiplier = currentMultiplier.add( 113 | diff.mul(divisor).div(totalNodeStaked) 114 | ); 115 | 116 | balanceBefore = balanceNow; 117 | currentMultiplier = multiplier; 118 | } 119 | 120 | function emergencyWithdraw() public { 121 | require(msg.sender == owner(), "!owner"); 122 | rewardToken.transfer(msg.sender, rewardToken.balanceOf(address(this))); 123 | swapContract = ISwapContract(address(0)); 124 | } 125 | 126 | // _updateOwed calculates and updates the total amount that is owed to an user and updates the user's multiplier 127 | // to the current value 128 | // it automatically attempts to pull the token from the source and acknowledge the funds 129 | function _updateOwed(address user, uint256 timestamp) internal { 130 | uint256 reward = _userPendingReward(user, timestamp); 131 | owed[user] = owed[user].add(reward); 132 | userMultiplier[user] = currentMultiplier; 133 | } 134 | 135 | // _userPendingReward calculates the reward that should be based on the current multiplier / anything that's not included in the `owed[user]` value 136 | // it does not represent the entire reward that's due to the user unless added on top of `owed[user]` 137 | function _userPendingReward( 138 | address user, 139 | uint256 timestamp 140 | ) internal view returns (uint256) { 141 | uint256 multiplier = currentMultiplier.sub(userMultiplier[user]); 142 | return barn.balanceAtTs(user, timestamp).mul(multiplier).div(divisor); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /docs/Diagrams/SkyPools Diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwingbyProtocol/skybridge-contract/48b50cf9c1bc6abe6d5744c90d7b4f7def1d8f54/docs/Diagrams/SkyPools Diagram.png -------------------------------------------------------------------------------- /docs/Diagrams/SkypoolsDiagram.drawio: -------------------------------------------------------------------------------- 1 | 7Z3bcuK4FoafJlXTF+nyOeSSQ5hJNR2oQPqwb1LCVsATYzGyCKSffku2bIxlTmmINBPRXRW8LAsjfVpa+iWLC7s9W/2JwXz6FQUwurCMYHVhdy4sy/auHfqHWV4zi+VZ3DLBYZDZzLVhGP6C3Ghw6yIMYLKRkCAUkXC+afRRHEOfbNgAxmi5mewJRZufOgcTKBiGPohE6/cwINPM2nCNtf0vGE6m+SebBj8zA3libkimIEDLksm+ubDbGCGSvZut2jBipZeXS3Zdd8vZ4sYwjMkhF3yb/bp7mT6YgfM/d/krdm8D/8slz+UFRAv+hS8sL6L5tZ4QzZbeNXnlReH9s0D5icskragmTWA25qv1Sfpuwv4Ol2DepgkxoHXCc6S3lmWaJeGlUuRvJctwFoGYHrWmZBZRo8k/bsgTsWMQhZOYvvfp14aYGl4gJiGtsCY/QdCcWv1pGAU98IoWrHASAvzn/Kg1RTj8RbMF+WfQ05hw9qzGRoohu5KaDWrFkH3tQV7iZmHqgYTwND6KIjBPwnFxwzOAJ2HcQoSgGU+Uf9NuGEVtFCGcFoD9lL5YrmgRBzDIU+fgZPnPQp+/j8AYRi16f5P0gjynGKVlmBCMngto06KsfJzL/vEi7oJZGLFG+g3iAMQgL/msUEyryLCUgZe+eMqSPXsVVcwqCK62UmsWbYF6EYhmkOBXmoRfYDV48+EOJD9crhuj63HbtNwQHcPjXoB7gEmR97qR0De8naSHaPw38yGWkZZsdlmnOWpmGe1sSFbpW/CGV492lee3g+odD2pm+gpWGwmPxbcMRmMHV2cCZrsjEynKu53GYdS4ubM+Ahp6yLk5wu/agt8FQUBrI2HfdTGOaBu3jNaoPXpsdjr3gqukxUOEAubtvlwb3JT7zAg+ka0eM5kDP4wnvTRNx1lb7nn5MBOi1z5FqTeahkEA49RbEUBARgzDY47CmKTl57bof1qibeOze+HSG2/TY3N9TP+z5JiyENPvAsK0iiHFcQkTUtNYKtwY9NXtVoj0fosjazdH3mEcWcf7nsO4cQ7hJpoTikWsqVGEGteSTI0rUDMD8zmtpD/W9GQxHo/MjDGNsT+VmVpOQwKjkJavpkoNqq4O7NPORpUnULWghdYoU+NPFziGwW3cpgGqRkcVdEzDkczO1X52SJKMptQ5TdmQXZOjCDn2geOvs5HT2E9OjAJ4D5cAB8k9ICHS9KhCjys7fr7eT08A5ygJSRfCpDUYanZUYachO4rOJeld8CxDMg0wWKKI8qPxUQcfy5AdLpui1s7wsZhPLI3dkf8Mg95gxEbwSRfhO9qZaYpUociWHTib1iEUPdHOSzOkKEOe7BDaFNXnGobCOCQhiG5W/hTEE0gjac2QMgw1ZAfSpqhElxjC4UuKC5uWZ98+m1DX9NTS024zft6RHjvvROTRIyrSdfRE8w70wxmIEs2OKuzY0uNoUXfeN5vB2fq0ARetRECaMyZM9580X6rw5UmPsEVtOudr/EpgYlsCX8VsWQHXIoFatFaGqWvpEbeoWu+dgc1Y28SKKdu6L1SFK8eUHoWLevbBM/sFVGFyG/f0zL5CXDmy43NLlLpznlhpdwSn1KRntWNSBiBPdpBuiWL3Psd0aBC/sSwpXeimwdsBXrv9nuBdy47eLVEf79/1flJL//vdzT392324a49u+3dD+v6P4Zefrfvbzp83DDf6wZYxGg4/CTz9d9dve5UW8ab124bheamDeztXu9dvu86hDi2foDk9WKJontDGH8ERBnHyBPHNfbt41OdjeqI6Iuo81Ik80b5pFtmeSFTIZ4uIhBu8jNiNRK8DwGZ9NTyqwCN9xbYlCuTMtUOfsCfr2NqkLsKtUVsjowoy0pdjW6IujqGPcHAbs4cG40mXCd4aGFWAkb8I2xKV7oyY/oJoZFRERvrqa0sUsjNkHkY/+sMlhPOvYQwx7aA0NcpQI33VtSXK1OmTQZoRZRiRvrraFiXnzLMMn18HCEXJ6IfG5aJG1pMyuJa+mtoWBebBQ6t3295U+LSOd5yOx9cxvh2c3Tre1cFupnE2cESB2E+b3cIntBw+sovZ5UpOT4q9Z8sO2UGLLQq+YTJaPeiVPQpRIl2os0WVdwJJe4HZ9xrg0Ie9gcZFFVyki3S2qOtSXDrFI6f6KQuVcJEv0dmiqEt5SWW5e5hA/KJpUYcW6eqcLQq6lJamT8IXeKeXjioFi3RRzhal3DGgg2MffvDHId5XadnHiXxhThRvAzQAGLCZaA2KKqDIl+QcUcENkHkb+9MRBh/8AXS1UJG+i4EjqrcYBhDOlnpNi0qgSN+qIH8SogTKLdv3Owbs0u4iprEtqlkAroX+nUK/d9VsXZ9T6DeNQx9BKB4oPj07ooD7GCbJApZ2RtELXI4YFZ2AGmfPvKLsQZEjyrmP4wWONTKqIiN9BsARJd1Hfwr9527EfqREg6IIKNK1f0fUch9BEGh/ohQm8jV/R1RxHzGc0YrRqKiFinTB3xE13Mfko8tyajEiXed3RP32MQFPxXOLmhVlWJGu9buihEu7nnQn9Xb2+FmIPvaqbaWAka/5u6KQy2JatkhutNKgKAOKdMU/H6bXgqJHyeqQIl3yd2tkW0qK3sNaKUykb0Ds1ii1yTwKyQh9YybtU5SBRf5+w66o0X65+SkQ8t+aNRR+KbkEgmVUoH+H323dPWPYqOl4rDpIzKuzUSIKtHdwyeaZ2YNBRv4g4mGOZaPYthW0qt6Dewt3izepW6Twdu+RNc5j5gRrucjFuNNjIeqxg3z/uWzPMBrFMkC6ad1pPE67kHYPHjX62jvjIWqwg3xvTE2CuAnm2UioCUnfmQRRaUVx9NpfxoeqrB+EhRPsF7iHBbNma+b3hcETpdSalWsai9OORPZh4UjHQhRMLywvykvrgv1kTl4g3j8LRNLisH0/9Z4lU7Yvbmn/0iwTelNZPvm+uRW+MFrEAQx4BaS/6j2knLCzSwzYkHZKZtGFMHK0jbpmnP/skTh6FgAu/H925juvgN8dPfAL7HzDPF7Rlw1xNOE0airaO1tFi4KnON6cgjl7+xTBVRNj1i5bMA74244fgSShYSYfUIrm+qoya6qqCNPhKiQ/WKLPhuXy45+s5X92bI8fd/JxZ3rwWjoYQBzS4mGjyU7NCLJSx9t7fxhM4LE1XapJ06gbF+ZGDCPAnnjb+IC6+uWfMWAOb41S/hhDTpLT+HztGcUrn07NM0zQAvuQ57FmRsjWNiuEuhXyaBVPIBEySuEriuE3eBRl1Vav3/7S/qt5e7eVTH8xhvv9xDhzKr1xYQD+8yR1Nf0FicI4d/gBwM991i2RlKrPhrtptFJrhWfLrfUaNU7nBI7k0mxU6t+0aoSJWgCds/kSUes8pNPgYVbJVKri3MgyuEzSkm7SBLYxX4ndzF2/U/QwY7zuXLZZ9vVCOV6LWdRMt11Z66s9MIbRgD0Oz8IjuzPmktYWAbZEIcpQo8FIDP1cKat4qCLyFDxUcSaq3EAhn+3S0+yDo9l9+FXcj+2I9JlXdRHLtXsu+kTxtELfG6l6GLIN2VUj5u31f0h4VLbXMHiMWrKbJNOwNknyDPkkiQLrO8VEZ6kflaMYs8go18kald7p0MClYVY6ROuwwIVWDXgtJePjyu13XAU273jXxGVZnjYsEsVdFZDc3j1t69DUR/LS2tK1HR1KV0fn5w6dRYX3nRix3DpG9oYw/15G3E1EnKs3ImJdVTq/9x5tiVKwVGT29mjb+kD1kWlUmGm8taMzjUpPd2W7J4KGHmLEYt91cjqInn5FAWQp/g8= -------------------------------------------------------------------------------- /docs/Diagrams/SkypoolsVisual.drawio: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwingbyProtocol/skybridge-contract/48b50cf9c1bc6abe6d5744c90d7b4f7def1d8f54/docs/Diagrams/SkypoolsVisual.drawio -------------------------------------------------------------------------------- /docs/Diagrams/SkypoolsVisual_Flow 1.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwingbyProtocol/skybridge-contract/48b50cf9c1bc6abe6d5744c90d7b4f7def1d8f54/docs/Diagrams/SkypoolsVisual_Flow 1.drawio.png -------------------------------------------------------------------------------- /docs/Diagrams/SkypoolsVisual_Flow 1.drawio.xml: -------------------------------------------------------------------------------- 1 | 2 | 3Zpdc6M2FIZ/DdPuRTJ8m1wmdrLtTHaTSdrZbm86MgijiYwYIa/t/voegfgU1M5ucNxeGR0JGd7z6PAK23Dm691HjrLkE4swNWwz2hnOwrBtywo8+JCRfRnxHRVYcRKpQU3gmfyNVdBU0Q2JcN4ZKBijgmTdYMjSFIeiE0Ocs213WMxo91sztMJa4DlEVI9+IZFIymjgmU38F0xWSfXNlql61qgarAJ5giK2bYWcW8OZc8ZEebTezTGV4lW6lOfdjfTWF8ZxKo45ASef7p7ugh37TK8vPv719Of91r5Qs3xDdKNu+Plln4HAOUSf14gL+JyzVHAE4pb3IfaVOJxt0gjL+S3DudkmRODnDIWydws4QCwRa6q61TdhLvBu9BasWhggCrM1FnwPQ9QJjq+0VDA5M9XeNqmxKr2TdlquVBApHFb13I1icKBEe4WAzpCAS0AZsDo3uWz3SLn8qdRyNbU+M7m8+0rBWsnkYbinBCTjzmG9lqW498s6gMKXVSH5w0bANFjF87LGWN7biFwLWDF5dSyTzlQqe5rKv+eYj4q8WdPrUDAOekglCBS/e7TE9JHlRBCWwpAlE4KtWwOuKVnJDsF6aWCl1vO6HJtvI7Pfl3lo6ZtDMs+mktnSi+cj4ijfAppDxdP8NRWYxxLgc6sMvnUstPZkauqV9O7+4QtE4J6v4ePmN5jYvDBsH62lIitRaGFuxzpun+YX8nLNn1kmOUb0gyY8SCi66iJFdohltgaQX5MokqffcAylBC2LqSTlGSOpKGTxbgxvIefaCFaVG1l5BGcvsDSoXGuLlMmSdBMTSnuhclxlN1w5CCBS3siaVW11F9Yb8FC5tH1VmjwNh3rBtXGYrIRZeg2zRgtYTPHuWno9UAankTpchBTlOQm76W1WmtnV1faKs+Hi/1BDi8bXdmOxU+eVrX01SyuFhu1ECAdxqOUbevwwwMu4XsI40rxnL2FgdhFfYXHIgOiJbWXOG0hcFeOYIkG+dS9jKJvqGx4l462qbHXriGv2gMjZhodYndU2pwcmcvoTlTpoExVw1bf9A7z5Gm/2xLwVHO2IkLiZl55q1bzBcYObbIzR5uEgcodoC+yl4/uvoq1M17nSVlurirZ++TmWttoIVxNZp6Wteoh2qlvxkFvgTLqu+nGH0khOloIRQwLLDJXuQrDmyScSgGyVyM7Rrcc7PufadW+sUrafb29kGD2zm+MBW24HA6xOZnBs3S7aZdJvdzjcjGW3JABRysKSAAHapnk1alM4exNcugRB9odju/X3ZaCuRmP1axIGer5mwOY6QzZ3OghsDQLnEtrlBs0MUVpcnUgijrYNBA9PPThQyiDbvMJBmlyZd5JucDXE/VA74nSZZ7WiZ0NE5C99b4CIOI7tcKqq0PMZ9Sa8TYRzUiL0fY/bLwtZs60czr5kBJwISVctInJcPPMiwmEnTvftivGTrB9bKCr43MrElT9z0AAU2IJCMZsIit67BcsbgGJo+zMdFPqLslPa0cqAfu1Y02E7KhuPmBO4ccnG+1tUJd3BjdMIE/8xK+v2rKwTnNjK6ht194Skmpeu67a3TpemefVqXuttP0zndbb+FyZMODuw/y9aB9ZAXb/GK94broFjXx5YZ7UI/P427HsXgX/itwe2/vbgFItgSsQOouO9Jzlu0Et4v+od/d7JPlCHpyZnppFzenBqwz1u0f+v4Lj9X4e+94Wl2/eCU4MTaOA4GjkyX8VPedP5+T5axpgdV3/QUJMZtXduI/QvS2TUvMMT2rKCqx+joxrC4jjHr8wXNJs/cZTDm7/COLf/AA== -------------------------------------------------------------------------------- /docs/Diagrams/SkypoolsVisual_Flow 2.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwingbyProtocol/skybridge-contract/48b50cf9c1bc6abe6d5744c90d7b4f7def1d8f54/docs/Diagrams/SkypoolsVisual_Flow 2.drawio.png -------------------------------------------------------------------------------- /docs/Diagrams/SkypoolsVisual_Flow 2.drawio.xml: -------------------------------------------------------------------------------- 1 | 2 | 3Zphc6I4GMc/jS/bASKIL1tt926mu+vU3uzuvbmJEDVTJE6Iq96nvyckIITQulVs93xRyEMS5P//5UlI7aHRaveJ4/XyM4tJ0vOceNdD457nuW7ow0FG9irih6EKLDiNdaVDYEr/JTro6OiGxiSrVRSMJYKu68GIpSmJRC2GOWfberU5S+p3XeMFaQSmEU6a0W80FksVDX3nEP+D0MWyuLPr6CsrXFTWgWyJY7athNBdD404Y0KdrXYjkkjxCl1Uu/uWq+UX4yQVxzQgy8/3j/fhjn1Jbq4+/fP498PWu9K9/MTJRj/w9Hm/BoEziE5XmAs4jlgqOAZx1XOIfSEOZ5s0JrJ/t4dut0sqyHSNI3l1CzhAbClWib6s70S4ILvWR3BLYYAowlZE8D1UKRoMBqqJhqlfULI9WOMWei+rtgx1EGscFmXfB8XgRIv2CwIim4AzQBmw+mhyeeGRcgVdqdVvqPWFyeFtKgVjZS1Po31CQTKOXtdrpsR9mJUBHD0vcsm/bgR0Q3Q8UznG9c8jct8zRPaOZRJ1pbLfUPmvjPBWkTer5CYSjIMeUgkKye8Bz0gyYRkVlKVQZcaEYKtKhZuELuQFwQwbmNJ6VKZj50wyoyOGvmOTedCVzG4zeU4wx9kW0LQlT+fPVBA+lwB/tMwQ+MdC63WmZjOT3j98/QYReI4bONw9jq7k3Z2rnhfglRRlIXI5nO3t08h6IY8bWoNqoi4o1jBHRBpkoXxF41g2v+UEsgee5V1JsNeMpiJXwr/t+WPZ10awIsPIZCM4e4bRkMjhNU6ZzEK3c5okRkjVK1YYfVkJuNHLIXdQlPVTuOdAoEg/+6LsNxAoJ4wqAp2lrQKtCgGusn5M1jIXVSF4ArnSj+Rtz0NBFJLZ3DAY4jEm4TwyPD1TXvS9uo1Dy0BGFhc7G8deMysWA3hHoo2A5OdU0qRgh/GL0xj+chIxLk/WJI1pupCLe84yuSCNlpim0vG87YfyPvRmKAgs3vskjM3x3JH3rmVORLYs3p35XsN8pMyf0OgZDpt1zdin76XtpKSjSkaKYQnyk3y8VC6tDWaBb7F8Pp970YWGezm2q1k7uKjlzXm7ryyfktxYw0Llq1jKwMa2LH1fU4fBAGGLqcSFkTy4kKm21Zh/UVOHlqm47f1hnpDdjdxqATXAcn06jhKcZTSqW3lY6Dp1LT1ZJjsqvutr8vyHPL9GxkdfHO8qNcf7SmFCOAUdJCrqNi3TcfsErp6VxI29IcNS0INteERekNK3W1+x1uZsEeMkwfnoqd7TZre+w0QCfyALGW9NvmMQo76+blXdPDI68obG61cwqHckMF8Q0egop6987BO2WWyriv8NkMUaoX1VcSyQ7wWa+XoOoF0H1Q86D3e+416Wu+bsdgJ3GXxbcQqOKTxNzuO1XxR/6JZ54YBgXtp3ztsRCbDYJlFOvVTxVYDtGzzOeRB2DdSC8Ey50jc76prZ5i4r+v2YLVOvalYk3xdzbdtCvH3pfk7Oj8QcvTPmoTGTm/s5R2NudITMjrrGvLnNfQLmb+C5SnMF7jaeZemVhcBZgX0VxP57LhiQU3/nQe4bMUR+vSPv0tk2aGDYvwSG1vTonroULV9z21+Mz5gy35XAfmAQaP6P+FgC+2ZGNV+y3kwgFA+/D1DVD7+yQHf/AQ== -------------------------------------------------------------------------------- /docs/Diagrams/SwapContractDetailed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwingbyProtocol/skybridge-contract/48b50cf9c1bc6abe6d5744c90d7b4f7def1d8f54/docs/Diagrams/SwapContractDetailed.png -------------------------------------------------------------------------------- /docs/Diagrams/UML_Image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwingbyProtocol/skybridge-contract/48b50cf9c1bc6abe6d5744c90d7b4f7def1d8f54/docs/Diagrams/UML_Image.png -------------------------------------------------------------------------------- /docs/Skybridge Security Audit Report - Red4Sec.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwingbyProtocol/skybridge-contract/48b50cf9c1bc6abe6d5744c90d7b4f7def1d8f54/docs/Skybridge Security Audit Report - Red4Sec.pdf -------------------------------------------------------------------------------- /docs/Skybridge Security Audit Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwingbyProtocol/skybridge-contract/48b50cf9c1bc6abe6d5744c90d7b4f7def1d8f54/docs/Skybridge Security Audit Report.pdf -------------------------------------------------------------------------------- /docs/lp-token-rate-logic.md: -------------------------------------------------------------------------------- 1 | # LP exchange rate logic 2 | 3 | 4 | In the first iteration of Skybridge v2, LP tokens represent ownership by the underlying assets from the pools, which are composed of **two assets meant to have the same value** (_"the bridged assets"_). 5 | 6 | The first iteration of Skybridge v2 will focus on a **BTC/WBTC pool**. This document explains the process on how LP exchange rate fluctuates, with a focus on the following cases: 7 | 8 | 1. Users swapping assets (WBTC -> BTC and BTC -> WBTC) 9 | 2. Liquidity providers depositing assets (aka minting LP tokens) 10 | 3. Liquidity providers withdrawing assets(aka burning LP tokens) 11 | 12 | Similar to other protocols like Compound or Uniswap, the price of the LP token is bound to increase over time to reflect the transaction fees being incorporated into the pools. 13 | 14 | ## 1. Description of the parameters and other notations 15 | 16 | ```initialExchangeRate```: LP token to BTC/WBTC (defined in the contract constructor). Part of the constructor of the LP contract, an arbitrary value must defined. 17 | ```currentExchangeRate```: 1 LP token to BTC (changes over time) 18 | ```amountReceivedByLP```: amount received owing to swap transaction fees. It is an accounting claim and is incorporated into the pools. 19 | 20 | ## 2. Case studies 21 | 22 | ### 2.1 Swap BTC --> WBTC 23 | 24 | When a swap is handled, part of the transaction fee is allocated to the SC and defined in the contract through the use of a field called ```amountReceivedByLP``` (in BTC). 25 | 26 | The fee calculation is handled at the node configuration scope (not at the smart contract level). 27 | 28 | Once the amount is paid to LPs (recorded as```amountReceivedByLP```), the ```currentExchangeRate``` must be re-calculated such as: 29 | 30 | ```currentExchangeRate = (newQuantityBTC + newQuantityWBTC)/(numberOfLPTokens)``` 31 | 32 | with (1) ```newQuantityBTC = initialQuantityBTC + quantityBTCSwapped + amountReceivedByLP``` 33 | and (2) ```newQuantityWBTC = initialQuantityWBTC - quantityWBTCSwapped ``` 34 | 35 | Since ```newQuantityBTC + newQuantityWBTC > initialQuantityBTC + initialQuantityWBTC```, the new ```currentExchangeRate``` **increases after every new swap**. 36 | 37 | ### 2.2 Swap WBTC --> BTC 38 | 39 | It follows a similar process as described in subsection 2.1. 40 | 41 | Once the fee is allocated and amount is received to the contract (and recorded as```amountReceivedByLP```), the ```currentExchangeRate``` must be re-calculated such as: 42 | 43 | ```currentExchangeRate = (newQuantityBTC + newQuantityWBTC)/(numberOfLPTokens)``` 44 | 45 | with (1) ```newQuantityBTC = initialQuantityBTC - quantityBTCSwapped``` 46 | and (2) ```newQuantityWBTC = initialQuantityWBTC + quantityWBTCSwapped + amountReceivedByLP``` 47 | 48 | Since ```newQuantityBTC + newQuantityWBTC > initialQuantityBTC + initialQuantityWBTC```, the new ```currentExchangeRate``` **increases after every new swap**. 49 | 50 | ### 2.3 Addition of liquidity to one side of the pool 51 | 52 | When a user wishes to add additional liquidity to one side of the pool, he/she must mint the LP token at the ```currentExchangeRate``` while depositing WBTC or BTC to their respective TSS addresses held by the protocol validators. 53 | 54 | #### 2.3.1 BTC deposit 55 | 56 | 1. The user deposits BTC using a special tag placed in the KV store that tells the system it is a float deposit. The swap is processed as normal by the nodes but the destination token becomes BTC-LP. 57 | 3. The parameter```currentExchangeRate``` is read by the contract. 58 | 4. The contract mints a quantity of BTC-LP token (1-1 representation) based on ```currentExchangeRate``` and ```amountDeposited``` (as supplied by the nodes) and sends the minted BTC-LP token to the user on Ethereum. 59 | 60 | **Adding BTC liquidity does not change the LP exchange rate (vs. BTC) since no fee is collected by LP providers**. 61 | 62 | However, ```numberOfLPTokens``` increases accordingly based on the quantity newly minted. 63 | 64 | #### 2.3.2 WBTC deposit 65 | 66 | 1. User sends the WBTC to the contract on Ethereum. 67 | 2. The contract mints a quantity of the BTC-LP token (1-1 representation) based on ```currentExchangeRate``` and ```amountDeposited``` (as supplied by the nodes) and sends the minted BTC-LP token to the user on Ethereum. 68 | 3. The contract credits the swap pool with the deposited WBTC. 69 | 70 | **Adding WBTC liquidity does not change the LP exchange rate (vs. BTC) since no fee is collected by LP providers**. 71 | 72 | However, ```numberOfLPTokens``` increases accordingly based on the quantity newly minted. 73 | 74 | ### 2.4 Removal of liquidity from one side of the pool 75 | 76 | When a user wishes to withdraw liquidity to one side of the pool, he must burn the LP token, indicate the asset he wishes to redeem his LP token to, while the ```currentExchangeRate``` is recorded part of the user's request. 77 | 78 | #### 2.4.1 WBTC redemption 79 | 80 | 1. User sends the BTC-LP token to the swap contract on Ethereum: `redeemFloat()`. 81 | 2. The swap contract sends the WBTC to the user on Ethereum. 82 | 3. Swap contract burns the received BTC-LP token. 83 | 84 | **Removing WBTC does not change the LP exchange rate (to BTC) since no fee is collected to LP providers**. 85 | 86 | #### 2.4.2 BTC redemption 87 | 88 | 1. User sends the BTC-LP token to the swap contract on Ethereum: `redeemFloat()`. 89 | 2. Swap contract burns the received BTC-LP token and sends the WBTC for swapping to BTC. 90 | 3. System sends the BTC to the user on the Bitcoin blockchain. 91 | 92 | **Removing BTC does change the LP exchange rate (to BTC)** since it is effectively a two-step process: 93 | (1) WBTC redemption (no change in the ```currentExchangeRate```) 94 | (2) a swap WBTC -> BTC (change in the ```currentExchangeRate```). 95 | 96 | Similarly, the```numberOfLPTokens``` also decreases accordingly based on the quantity burnt. -------------------------------------------------------------------------------- /docs/readme.md: -------------------------------------------------------------------------------- 1 | # Contract Design Docs 2 | 3 | ## Table of Contents 4 | 5 | - [LP Exchange Rate Logic](./lp-token-rate-logic.md) 6 | - [Swap Contract Specification](./swap_contract_spec.md) 7 | -------------------------------------------------------------------------------- /docs/support_bsc.md: -------------------------------------------------------------------------------- 1 | # Swap Contract upgraded for BSC network 2 | 3 | ## TL;DR 4 | * The swap contract has storages for decimal `8` tokens. 5 | * To support decimal `18` BTC pegged tokens, the contract is upgraded. 6 | * The contract supports transfer for [BTCB](https://testnet.bscscan.com/token/0x6ce8da28e2f864420840cf74474eff5fd80e65b8) 7 | * A new function `_safeTransfer()` handles ERC20 token transfer with `boosting` amount. 8 | * LP token decimal is kept `8`. 9 | * The float balance states are still decimal `8` basis. 10 | * All transfer input params are still decimal `8` basis 11 | 12 | 13 | ### Contract interface changed 14 | 15 | The new LP Token contract has a new consturctor `_decimals` which is for set LP token decimals. 16 | ```js 17 | constructor(uint8 _decimals) { 18 | _initialize("Swingby BTC LP Token", "sbBTC", _decimals, 0, true); 19 | } 20 | ``` 21 | 22 | ### A new internal function `_safeTransfer()` is added for amount boosting 23 | 24 | A new function added for sending decimals `18` token, `convertScale` is set `10 ** (btct.decimals - lpToken.decimals)`. 25 | thus, it is set `10 ** 10`in transfer `18` decimal tokens case. 26 | ```js 27 | /// @dev _safeTransfer executes tranfer erc20 tokens 28 | /// @param _token The address of target token 29 | /// @param _to The address of receiver. 30 | /// @param _amount The amount of transfer. 31 | function _safeTransfer( 32 | address _token, 33 | address _to, 34 | uint256 _amount 35 | ) internal { 36 | if (_token == BTCT_ADDR) { 37 | _amount = _amount.mul(convertScale); 38 | } 39 | require(IERC20(_token).transfer(_to, _amount)); 40 | } 41 | ``` 42 | 43 | 44 | ### TIPS: Swingby node has to check ERC20 transfer amount of the refund case. 45 | The swap contract has to refund the amount of the received `BTCT` even decimal is 18. 46 | the tx input params which is for 'transfer are decimal `8` basis, so a tx input should be converted `8` from `18`. 47 | All transfer functions are just supported boosting the transfer of decimal `8` basis amount. thus, the small amount of received tx will be left in the swap contract. (that is not collected into as float balances, it will left forever) -------------------------------------------------------------------------------- /hardhat.config.js: -------------------------------------------------------------------------------- 1 | 2 | //npx hardhat run scripts/deploy.js --network 3 | //run the tests: npx hardhat test 4 | //Plugins to let hardhat use web3 and truffle libraries 5 | require("@nomiclabs/hardhat-web3"); 6 | require("hardhat-watcher"); 7 | require('@symblox/hardhat-abi-gen'); 8 | require('@nomiclabs/hardhat-etherscan'); 9 | require("@nomiclabs/hardhat-waffle"); 10 | //const mnemonic = process.env.SEED 11 | 12 | //This requires a private key rather than a memonic, this is a private key to a throw away account so this can compile, but it should be stored in a local secret.json file 13 | //It could then be accessed below using secret.key 14 | // const mnemonic = process.env.KEY || "4d777ee25c2bb753c12597e8f35a2eedb90ece9bc5682f335e0e2c2fdc8d5674" 15 | const accountInfo = { 16 | mnemonic: process.env.MNEMONIC, 17 | path: "m/44'/60'/0'/0", 18 | initialIndex: 1, 19 | count: 20, 20 | passphrase: "", 21 | } 22 | 23 | module.exports = { 24 | //defaultNetwork: "hardhat", 25 | watcher: { 26 | compilation: { //npx hardhat watch compilation -- auto compile on change 27 | tasks: ["compile"], 28 | }, 29 | test: {//npx hardhat watch test -- run test when a file is saved 30 | tasks: [{ command: 'test', params: { testFiles: ['./test/testSkyPoolsV2.js'] } }], //test this file 31 | files: ['./test/testSkyPoolsV2.js'] //test when this file is saved 32 | } 33 | }, 34 | solidity: { 35 | version: "0.8.19", 36 | settings: { 37 | optimizer: { 38 | enabled: true, 39 | runs: 1000 40 | } 41 | } 42 | }, 43 | networks: { 44 | development: { 45 | url: "http://127.0.0.1:8545", 46 | accounts: accountInfo, 47 | confirmations: 2, 48 | skipDryRun: true, 49 | gas: "auto", 50 | gasPrice: "auto", 51 | maxPriorityFeePerGas: 1000000000, 52 | }, 53 | hardhat: { 54 | //run tests on fork of mainnet 55 | // forking: { 56 | // url: "https://eth-mainnet.alchemyapi.io/v2/YfblHzLI_PlnIA0pxphS90J3yaA3dDi5", 57 | // blockNumber: 17322134 //13220045 //previous testing block 58 | // } 59 | }, 60 | goerli: { 61 | url: "https://goerli.infura.io/v3/f35c2a4f3d0941a38a3edb62ed10c847", 62 | accounts: accountInfo, 63 | network_id: 5, // Ropsten's id 64 | gas: "auto", // Ropsten has a lower block limit than mainnet 65 | confirmations: 2, // # of confs to wait between deployments. (default: 0) 66 | timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50) 67 | skipDryRun: true, // Skip dry run before migrations? (default: false for public nets ) 68 | gasPrice: "auto", 69 | maxPriorityFeePerGas: 1000000000, 70 | }, 71 | mainnet: { 72 | url: "https://mainnet.infura.io/v3/f35c2a4f3d0941a38a3edb62ed10c847", 73 | accounts: accountInfo, 74 | network_id: 1, // Ropsten's id 75 | gas: "auto", // Ropsten has a lower block limit than mainnet 76 | confirmations: 2, // # of confs to wait between deployments. (default: 0) 77 | timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50) 78 | skipDryRun: true, // Skip dry run before migrations? (default: false for public nets ) 79 | gasPrice: "auto", 80 | maxPriorityFeePerGas: 1000000000, 81 | }, 82 | bsc_testnet: { 83 | url: "https://mainnet.infura.io/v3/f35c2a4f3d0941a38a3edb62ed10c847", 84 | accounts: accountInfo, 85 | network_id: 97, // Ropsten's id 86 | gas: 7500000, // Ropsten has a lower block limit than mainnet 87 | confirmations: 2, // # of confs to wait between deployments. (default: 0) 88 | timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50) 89 | skipDryRun: true, // Skip dry run before migrations? (default: false for public nets ) 90 | gasPrice: 10000000000 91 | }, 92 | bsc_mainnet: { 93 | url: "https://mainnet.infura.io/v3/f35c2a4f3d0941a38a3edb62ed10c847", 94 | accounts: accountInfo, 95 | network_id: 56, // Ropsten's id 96 | gas: 3000000, // Ropsten has a lower block limit than mainnet 97 | confirmations: 2, // # of confs to wait between deployments. (default: 0) 98 | timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50) 99 | skipDryRun: true, // Skip dry run before migrations? (default: false for public nets ) 100 | gasPrice: 10000000000 101 | } 102 | // Useful for private networks 103 | // private: { 104 | // provider: () => new HDWalletProvider(mnemonic, `https://network.io`), 105 | // network_id: 2111, // This network is yours, in the cloud. 106 | // production: true // Treats this network as if it was a public net. (default: false) 107 | // } 108 | }, 109 | // Set default mocha options here, use special reporters etc. 110 | mocha: { 111 | timeout: 100000 112 | }, 113 | 114 | etherscan: { 115 | apiKey: "A7EAG5WB4FRAHIURRGWD8HSTM8CVYXZGZ4" 116 | }, 117 | 118 | abiExporter: { 119 | path: './abi', 120 | clear: false, 121 | flat: true, 122 | spacing: 2 123 | }, 124 | 125 | plugins: [ 126 | "@chainsafe/truffle-plugin-abigen" 127 | ] 128 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "skybridge-contract", 3 | "version": "1.0.0", 4 | "description": "## Environment - testrpc (ganache) - v2.4.0 - truffle - v5.1.54 - solc - v0.7.5 - web3 - v1.2.9", 5 | "main": "truffle-config.js", 6 | "directories": { 7 | "doc": "docs", 8 | "test": "test" 9 | }, 10 | "scripts": { 11 | "build": "npm run compile && rm -rf abigenBindings && truffle run abigen && npm run test", 12 | "test": "npx hardhat test ./test/testSwapContract.js", 13 | "lint": "eslint --fix . --ext .js", 14 | "compile": "truffle compile", 15 | "gen-go": "node scripts/generateGoBindings.js" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/SwingbyProtocol/skybridge-contract.git" 20 | }, 21 | "author": "", 22 | "license": "SEE LICENSE IN LICENSE", 23 | "bugs": { 24 | "url": "https://github.com/SwingbyProtocol/skybridge-contract/issues" 25 | }, 26 | "homepage": "https://github.com/SwingbyProtocol/skybridge-contract#readme", 27 | "dependencies": { 28 | "@chainsafe/truffle-plugin-abigen": "0.0.2", 29 | "@nomiclabs/hardhat-etherscan": "^3.0.3", 30 | "@openzeppelin/contracts": "^4.3.2", 31 | "@symblox/hardhat-abi-gen": "^0.2.0", 32 | "@truffle/hdwallet-provider": "^2.0.8", 33 | "axios": "^0.21.1", 34 | "chai-as-promised": "^7.1.1", 35 | "dotenv": "^8.2.0", 36 | "elliptic": ">=6.5.4", 37 | "hardhat-watcher": "^2.1.1", 38 | "install": "^0.13.0", 39 | "json-parser": "^3.1.2", 40 | "node-fetch": ">=2.6.1", 41 | "npm": "^8.12.1", 42 | "sol2uml": "^1.1.6", 43 | "truffle-contract-size": "^2.0.1", 44 | "truffle-hdwallet-provider-privkey": "^0.0.4", 45 | "truffle-plugin-verify": "^0.5.15", 46 | "ts-node": "^10.9.1", 47 | "typescript": "^5.0.4" 48 | }, 49 | "devDependencies": { 50 | "@nomiclabs/hardhat-ethers": "^2.0.2", 51 | "@nomiclabs/hardhat-truffle5": "^2.0.0", 52 | "@nomiclabs/hardhat-waffle": "^2.0.1", 53 | "@nomiclabs/hardhat-web3": "^2.0.0", 54 | "@openzeppelin/hardhat-upgrades": "^1.18.1", 55 | "@openzeppelin/test-helpers": "^0.5.10", 56 | "chai": "^4.3.4", 57 | "eslint": "^7.22.0", 58 | "ethereum-waffle": "^3.4.0", 59 | "ethers": "^5.4.1", 60 | "hardhat": "^2.6.7", 61 | "truffle-flattener": "^1.5.0", 62 | "web3": "^1.4.0" 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /scripts/addFloat.js: -------------------------------------------------------------------------------- 1 | 2 | const { BN, constants } = require('@openzeppelin/test-helpers'); 3 | const { ZERO_ADDRESS } = constants 4 | const SwapContract = artifacts.require("SwapContract"); 5 | 6 | module.exports = async function (done) { 7 | // await deployer.deploy(LPToken) 8 | try { 9 | const swap = await SwapContract.deployed() 10 | // send 0.1 BTC as float 11 | let amount = new BN(131122121817231).mul(new BN(10).pow(new BN(1))) 12 | let to = process.env.TO 13 | let float = "0x" + web3.utils.padLeft(amount.toString('hex') + to.slice(2), 64) 14 | let isZerofees = false 15 | let txid = "0x1c12143203a48f42cdf7b1acee5b1b1c1fedc144cb309a3bf5edbffafb0ad734" 16 | let btct = await swap.BTCT_ADDR() 17 | await swap.recordIncomingFloat(btct.toString(), float, isZerofees, txid) 18 | } catch (err) { 19 | console.log(err) 20 | } 21 | done() 22 | }; 23 | -------------------------------------------------------------------------------- /scripts/addFloatNew.js: -------------------------------------------------------------------------------- 1 | const { ZERO_ADDRESS } = require("@openzeppelin/test-helpers/src/constants"); 2 | const { ethers } = require("hardhat"); 3 | BN = require('bn.js') 4 | /********************************************************************* 5 | * 6 | * Boiler Plate script to deploy 7 | * 8 | * July 28, 2021 9 | * 10 | * Deploy with: 11 | * npx hardhat run ./scripts/deploy.js --network development || npx hardhat run ./scripts/deploy.js --network hardhat 12 | * There are still some errors with the above 13 | */ 14 | async function main() { 15 | const swapContrat = '0x9e6BA6e811665849f03f56C1f22a8894AEbb3993' 16 | const to = '0x63d9f6A25ddD2c586F4441065Ce7C8412fbBB91e' 17 | const SwapContractFactory = await ethers.getContractFactory("SwapContract"); 18 | const swap = await SwapContractFactory.attach(swapContrat); 19 | 20 | // send 1 BTC & 1WBTC as float 21 | let amount = new BN(1).mul(new BN(10).pow(new BN(8))) 22 | let float = "0x" + web3.utils.padLeft(amount.toString('hex') + to.slice(2), 64) 23 | let txid_1 = "0x1c12143203a48f42cdf7b1acee5b1b1c1fedc144cb309a3bf5edbffafc0ad734" 24 | let txid_2 = "0x6a167c4b6750c3213320098178f913478fe50d3f75d5f0377ee7cec9a630ad9e" 25 | let btct = await swap.BTCT_ADDR() 26 | await swap.recordIncomingFloat(btct.toString(), float, txid_1) 27 | await swap.recordIncomingFloat(ZERO_ADDRESS, float, txid_2) 28 | } 29 | 30 | main() 31 | .then(() => process.exit(0)) 32 | .catch((error) => { 33 | console.error(error); 34 | process.exit(1); 35 | }); -------------------------------------------------------------------------------- /scripts/addNode.js: -------------------------------------------------------------------------------- 1 | const { ZERO_ADDRESS } = require("@openzeppelin/test-helpers/src/constants"); 2 | const { ethers } = require("hardhat"); 3 | BN = require('bn.js') 4 | /********************************************************************* 5 | * 6 | * Boiler Plate script to deploy 7 | * 8 | * July 28, 2021 9 | * 10 | * Deploy with: 11 | * npx hardhat run ./scripts/deploy.js --network development || npx hardhat run ./scripts/deploy.js --network hardhat 12 | * There are still some errors with the above 13 | */ 14 | async function main() { 15 | [sender, receiver, dao, ...addrs] = await ethers.getSigners(); 16 | console.log(sender.address) 17 | 18 | const swapContrat = '0x9e6BA6e811665849f03f56C1f22a8894AEbb3993' // goerli 19 | const to = '0x63d9f6A25ddD2c586F4441065Ce7C8412fbBB91e' 20 | const SwapContractFactory = await ethers.getContractFactory("SwapContract"); 21 | const swap = await SwapContractFactory.attach(swapContrat); 22 | 23 | let nodes = [] 24 | let isRemoved = [] 25 | let churnedInCount = 25 26 | let tssThreshold = 16 27 | let nodeRewardsRatio = 66 28 | // for 17 nodes adding 29 | nodes.push(sender.address) 30 | isRemoved.push(false) 31 | nodes.push(receiver.address) 32 | isRemoved.push(false) 33 | nodes.push(dao.address) 34 | isRemoved.push(false) 35 | 36 | for (i = 0; i < 8; i++) { 37 | nodes.push(addrs[i].address) 38 | isRemoved.push(false) 39 | } 40 | 41 | const tx1 = await swap.churn( 42 | sender.address, 43 | nodes, 44 | isRemoved, 45 | churnedInCount, 46 | tssThreshold, 47 | { 48 | value: 0, 49 | gasPrice: 2 * 10 ** 6 50 | }) 51 | 52 | const receipt = await tx1.wait() 53 | console.log(receipt) 54 | } 55 | 56 | main() 57 | .then(() => process.exit(0)) 58 | .catch((error) => { 59 | console.error(error); 60 | process.exit(1); 61 | }); -------------------------------------------------------------------------------- /scripts/burnToken.js: -------------------------------------------------------------------------------- 1 | const { BN } = require('@openzeppelin/test-helpers'); 2 | 3 | const SwingbyToken = artifacts.require("SwingbyToken"); 4 | 5 | module.exports = async function (done) { 6 | // await deployer.deploy(LPToken) 7 | try { 8 | const token = await SwingbyToken.at("0x423fa1c32541b3d9fc3690e15392185753d44fad") 9 | console.log("token:", token.address) 10 | let amount = new BN(1000000).mul(new BN(10).pow(new BN(18))) 11 | await token.burn(amount) 12 | } catch (err) { 13 | console.log(err) 14 | } 15 | done() 16 | }; 17 | -------------------------------------------------------------------------------- /scripts/deploy-goerli.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require("hardhat"); 2 | 3 | /********************************************************************* 4 | * 5 | * Boiler Plate script to deploy 6 | * 7 | * July 28, 2021 8 | * 9 | * Deploy with: 10 | * npx hardhat run ./scripts/deploy.js --network development || npx hardhat run ./scripts/deploy.js --network hardhat 11 | * There are still some errors with the above 12 | */ 13 | const TOKEN_DECIMALS = process.env.TOKEN_DECIMALS || 8 14 | async function main() { 15 | const [deployer] = await ethers.getSigners(); 16 | //let BTCT_ADDR = "0x449268b65BAf7251f83fd0a4b182DbC4C20985Fd" 17 | //BTCT_ADDR = "0xbde8bb00a7ef67007a96945b3a3621177b615c44" 18 | //BTCT_ADDR = "0xaD6D458402F60fD3Bd25163575031ACDce07538D"//address for DAI as there is no liquidity for BTCt on Ropsten 19 | const BTCT_ADDR = "0xEb47a21C1fC00D1E863019906df1771b80DBE182" 20 | const sbBTCPool = "0xec2946aD323f0879269910cbBB5420E8CD578a30" 21 | const swapRewards = "0xF4c381d077272295641F8A53D850d9a8125e0e94" 22 | const dao = "0xA740E20712C630d602D5007b618a1d604D3f41e9" 23 | const initialBTC = 1111 24 | const initialWBTC = 1111 25 | console.log("Deploying contracts with the account:", deployer.address); 26 | 27 | console.log("Account balance:", (await deployer.getBalance() / 1e18).toFixed(8)); 28 | 29 | const LPTokenFactory = await ethers.getContractFactory("LPToken"); 30 | const lpToken = await LPTokenFactory.deploy(TOKEN_DECIMALS); 31 | 32 | await lpToken.deployed(); 33 | console.log("LPToken address:", lpToken.address); 34 | 35 | const SwapContractFactory = await ethers.getContractFactory("SwapContract"); 36 | const swap = await SwapContractFactory.deploy( 37 | lpToken.address, 38 | BTCT_ADDR, 39 | sbBTCPool, 40 | swapRewards, 41 | dao, 42 | initialBTC, 43 | initialWBTC); 44 | 45 | await swap.deployed(); 46 | console.log("SwapContract address:", swap.address); 47 | } 48 | 49 | main() 50 | .then(() => process.exit(0)) 51 | .catch((error) => { 52 | console.error(error); 53 | process.exit(1); 54 | }); -------------------------------------------------------------------------------- /scripts/deploy-mainnet.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require("hardhat"); 2 | 3 | /********************************************************************* 4 | * 5 | * Boiler Plate script to deploy 6 | * 7 | * July 28, 2021 8 | * 9 | * Deploy with: 10 | * npx hardhat run ./scripts/deploy.js --network development || npx hardhat run ./scripts/deploy.js --network hardhat 11 | * There are still some errors with the above 12 | */ 13 | const TOKEN_DECIMALS = process.env.TOKEN_DECIMALS || 8 14 | async function main() { 15 | const [deployer] = await ethers.getSigners(); 16 | //let BTCT_ADDR = "0x449268b65BAf7251f83fd0a4b182DbC4C20985Fd" 17 | //BTCT_ADDR = "0xbde8bb00a7ef67007a96945b3a3621177b615c44" 18 | //BTCT_ADDR = "0xaD6D458402F60fD3Bd25163575031ACDce07538D"//address for DAI as there is no liquidity for BTCt on Ropsten 19 | const BTCT_ADDR = "0x7cb2eac36b4bb7c36640f32e806d33e474d1d427" 20 | const wETH_ADDR = "0xc778417e063141139fce010982780140aa0cd5ab" 21 | const sbBTCPool = "0xf5329508Fdb96A1aada673dB6572109a228edB7e" 22 | const params = "0xad2CD8327BFE0E8C059EA5f789d064ba4C261BDb" 23 | const swapRewards = "0x53E79243D27DCd5E1070b4B71FDC42F8944a7848" 24 | 25 | console.log("Deploying contracts with the account:", deployer.address); 26 | 27 | console.log("Account balance:", (await deployer.getBalance()/1e18).toString()); 28 | 29 | const LPTokenFactory = await ethers.getContractFactory("LPToken"); 30 | const lpToken = await LPTokenFactory.deploy(TOKEN_DECIMALS); 31 | 32 | await lpToken.deployed(); 33 | console.log("LPToken address:", lpToken.address); 34 | 35 | const SwapContractFactory = await ethers.getContractFactory("SwapContract"); 36 | const swap = await SwapContractFactory.deploy(lpToken.address, BTCT_ADDR, wETH_ADDR, sbBTCPool, params, swapRewards, 0); 37 | 38 | await swap.deployed(); 39 | console.log("SwapContract address:", swap.address); 40 | } 41 | 42 | main() 43 | .then(() => process.exit(0)) 44 | .catch((error) => { 45 | console.error(error); 46 | process.exit(1); 47 | }); -------------------------------------------------------------------------------- /scripts/deploy-ropsten.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require("hardhat"); 2 | 3 | /********************************************************************* 4 | * 5 | * Boiler Plate script to deploy 6 | * 7 | * July 28, 2021 8 | * 9 | * Deploy with: 10 | * npx hardhat run ./scripts/deploy.js --network development || npx hardhat run ./scripts/deploy.js --network hardhat 11 | * There are still some errors with the above 12 | */ 13 | const TOKEN_DECIMALS = process.env.TOKEN_DECIMALS || 8 14 | async function main() { 15 | const [deployer] = await ethers.getSigners(); 16 | //let BTCT_ADDR = "0x449268b65BAf7251f83fd0a4b182DbC4C20985Fd" 17 | //BTCT_ADDR = "0xbde8bb00a7ef67007a96945b3a3621177b615c44" 18 | //BTCT_ADDR = "0xaD6D458402F60fD3Bd25163575031ACDce07538D"//address for DAI as there is no liquidity for BTCt on Ropsten 19 | const BTCT_ADDR = "0x7cb2eac36b4bb7c36640f32e806d33e474d1d427" 20 | const wETH_ADDR = "0xc778417e063141139fce010982780140aa0cd5ab" 21 | const sbBTCPool = "0xf5329508Fdb96A1aada673dB6572109a228edB7e" 22 | const params = "0xad2CD8327BFE0E8C059EA5f789d064ba4C261BDb" 23 | const swapRewards = "0x53E79243D27DCd5E1070b4B71FDC42F8944a7848" 24 | 25 | console.log("Deploying contracts with the account:", deployer.address); 26 | 27 | console.log("Account balance:", (await deployer.getBalance()).toString()); 28 | 29 | const LPTokenFactory = await ethers.getContractFactory("LPToken"); 30 | const lpToken = await LPTokenFactory.deploy(TOKEN_DECIMALS); 31 | 32 | await lpToken.deployed(); 33 | console.log("LPToken address:", lpToken.address); 34 | 35 | const SwapContractFactory = await ethers.getContractFactory("SwapContract"); 36 | const swap = await SwapContractFactory.deploy(lpToken.address, BTCT_ADDR, wETH_ADDR, sbBTCPool, params, swapRewards, 0); 37 | 38 | await swap.deployed(); 39 | console.log("SwapContract address:", swap.address); 40 | } 41 | 42 | main() 43 | .then(() => process.exit(0)) 44 | .catch((error) => { 45 | console.error(error); 46 | process.exit(1); 47 | }); -------------------------------------------------------------------------------- /scripts/deploy-sbBTCPool.ts: -------------------------------------------------------------------------------- 1 | const { ethers } = require("hardhat"); 2 | 3 | const _owner = '0x64496f51779e400C5E955228E56fA41563Fb4dd8'; 4 | const _sbBTC = '0x1B5B6dF2C72D7c406df1C30E640df8dBaE57d21d'; 5 | const _barn = '0x009cc14ce70b2e667984c2276490d56ae3234c43'; 6 | const _swap = '0xe8d45281d7BD836b30F9B371001676d1ed59465D' 7 | 8 | async function main() { 9 | const sbBTCFactory = await ethers.getContractFactory("sbBTCPool"); 10 | 11 | const [owner] = await ethers.getSigners(); 12 | console.log(owner.address) 13 | const sbBTCPool = await sbBTCFactory.deploy(); 14 | console.log(`sbBTCPool deployed at: ${sbBTCPool.address}`); 15 | 16 | // await sbBTCPool.setBarnAndSwap(_barn, _swap); 17 | } 18 | 19 | main() 20 | .then(() => process.exit(0)) 21 | .catch((error) => { 22 | console.error(error); 23 | process.exit(1); 24 | }); -------------------------------------------------------------------------------- /scripts/deployParams.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require("hardhat"); 2 | 3 | /********************************************************************* 4 | * 5 | * Boiler Plate script to deploy 6 | * 7 | * July 28, 2021 8 | * 9 | * Deploy with: 10 | * npx hardhat run ./scripts/deploy.js --network development || npx hardhat run ./scripts/deploy.js --network hardhat 11 | * There are still some errors with the above 12 | */ 13 | async function main() { 14 | const ParamsFactory = await ethers.getContractFactory("Params"); 15 | const param = await ParamsFactory.deploy(); 16 | 17 | await param.deployed(); 18 | console.log("Params address:", param.address); 19 | } 20 | 21 | main() 22 | .then(() => process.exit(0)) 23 | .catch((error) => { 24 | console.error(error); 25 | process.exit(1); 26 | }); -------------------------------------------------------------------------------- /scripts/deploySwapRewards.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require("hardhat"); 2 | 3 | /********************************************************************* 4 | * 5 | * Boiler Plate script to deploy 6 | * 7 | * July 28, 2021 8 | * 9 | * Deploy with: 10 | * npx hardhat run ./scripts/deploy.js --network development || npx hardhat run ./scripts/deploy.js --network hardhat 11 | * There are still some errors with the above 12 | */ 13 | async function main() { 14 | const [deployer] = await ethers.getSigners(); 15 | //const SWINGBY = "0x8287C7b963b405b7B8D467DB9d79eEC40625b13A" 16 | const SWINGBY = "0xFCd51B56e65605C33024A9E98a7aaDfF2e1A15b9" // goerli 17 | const SwapRewardsFactory = await ethers.getContractFactory("SwapRewards"); 18 | const swapRewards = await SwapRewardsFactory.deploy(deployer.address, SWINGBY, 358520); 19 | 20 | await swapRewards.deployed(); 21 | console.log("SwapRewards address:", swapRewards.address); 22 | } 23 | 24 | main() 25 | .then(() => process.exit(0)) 26 | .catch((error) => { 27 | console.error(error); 28 | process.exit(1); 29 | }); -------------------------------------------------------------------------------- /scripts/deploySwingbyToken.js: -------------------------------------------------------------------------------- 1 | const SwingbyToken = artifacts.require("SwingbyToken"); 2 | 3 | module.exports = async function (done) { 4 | // await deployer.deploy(LPToken) 5 | try { 6 | const st = await SwingbyToken.new() 7 | console.log(st.address) 8 | } catch (err) { 9 | console.log(err) 10 | } 11 | done() 12 | }; 13 | -------------------------------------------------------------------------------- /scripts/erc20ABI.js: -------------------------------------------------------------------------------- 1 | 2 | class ERC20ABI{ 3 | 4 | erc20ABI() { 5 | return [ 6 | { 7 | "constant": true, 8 | "inputs": [], 9 | "name": "name", 10 | "outputs": [ 11 | { 12 | "name": "", 13 | "type": "string" 14 | } 15 | ], 16 | "payable": false, 17 | "stateMutability": "view", 18 | "type": "function" 19 | }, 20 | { 21 | "constant": false, 22 | "inputs": [ 23 | { 24 | "name": "_spender", 25 | "type": "address" 26 | }, 27 | { 28 | "name": "_value", 29 | "type": "uint256" 30 | } 31 | ], 32 | "name": "approve", 33 | "outputs": [ 34 | { 35 | "name": "", 36 | "type": "bool" 37 | } 38 | ], 39 | "payable": false, 40 | "stateMutability": "nonpayable", 41 | "type": "function" 42 | }, 43 | { 44 | "constant": true, 45 | "inputs": [], 46 | "name": "totalSupply", 47 | "outputs": [ 48 | { 49 | "name": "", 50 | "type": "uint256" 51 | } 52 | ], 53 | "payable": false, 54 | "stateMutability": "view", 55 | "type": "function" 56 | }, 57 | { 58 | "constant": false, 59 | "inputs": [ 60 | { 61 | "name": "_from", 62 | "type": "address" 63 | }, 64 | { 65 | "name": "_to", 66 | "type": "address" 67 | }, 68 | { 69 | "name": "_value", 70 | "type": "uint256" 71 | } 72 | ], 73 | "name": "transferFrom", 74 | "outputs": [ 75 | { 76 | "name": "", 77 | "type": "bool" 78 | } 79 | ], 80 | "payable": false, 81 | "stateMutability": "nonpayable", 82 | "type": "function" 83 | }, 84 | { 85 | "constant": true, 86 | "inputs": [], 87 | "name": "decimals", 88 | "outputs": [ 89 | { 90 | "name": "", 91 | "type": "uint8" 92 | } 93 | ], 94 | "payable": false, 95 | "stateMutability": "view", 96 | "type": "function" 97 | }, 98 | { 99 | "constant": true, 100 | "inputs": [ 101 | { 102 | "name": "_owner", 103 | "type": "address" 104 | } 105 | ], 106 | "name": "balanceOf", 107 | "outputs": [ 108 | { 109 | "name": "balance", 110 | "type": "uint256" 111 | } 112 | ], 113 | "payable": false, 114 | "stateMutability": "view", 115 | "type": "function" 116 | }, 117 | { 118 | "constant": true, 119 | "inputs": [], 120 | "name": "symbol", 121 | "outputs": [ 122 | { 123 | "name": "", 124 | "type": "string" 125 | } 126 | ], 127 | "payable": false, 128 | "stateMutability": "view", 129 | "type": "function" 130 | }, 131 | { 132 | "constant": false, 133 | "inputs": [ 134 | { 135 | "name": "_to", 136 | "type": "address" 137 | }, 138 | { 139 | "name": "_value", 140 | "type": "uint256" 141 | } 142 | ], 143 | "name": "transfer", 144 | "outputs": [ 145 | { 146 | "name": "", 147 | "type": "bool" 148 | } 149 | ], 150 | "payable": false, 151 | "stateMutability": "nonpayable", 152 | "type": "function" 153 | }, 154 | { 155 | "constant": true, 156 | "inputs": [ 157 | { 158 | "name": "_owner", 159 | "type": "address" 160 | }, 161 | { 162 | "name": "_spender", 163 | "type": "address" 164 | } 165 | ], 166 | "name": "allowance", 167 | "outputs": [ 168 | { 169 | "name": "", 170 | "type": "uint256" 171 | } 172 | ], 173 | "payable": false, 174 | "stateMutability": "view", 175 | "type": "function" 176 | }, 177 | { 178 | "payable": true, 179 | "stateMutability": "payable", 180 | "type": "fallback" 181 | }, 182 | { 183 | "anonymous": false, 184 | "inputs": [ 185 | { 186 | "indexed": true, 187 | "name": "owner", 188 | "type": "address" 189 | }, 190 | { 191 | "indexed": true, 192 | "name": "spender", 193 | "type": "address" 194 | }, 195 | { 196 | "indexed": false, 197 | "name": "value", 198 | "type": "uint256" 199 | } 200 | ], 201 | "name": "Approval", 202 | "type": "event" 203 | }, 204 | { 205 | "anonymous": false, 206 | "inputs": [ 207 | { 208 | "indexed": true, 209 | "name": "from", 210 | "type": "address" 211 | }, 212 | { 213 | "indexed": true, 214 | "name": "to", 215 | "type": "address" 216 | }, 217 | { 218 | "indexed": false, 219 | "name": "value", 220 | "type": "uint256" 221 | } 222 | ], 223 | "name": "Transfer", 224 | "type": "event" 225 | } 226 | ] 227 | } 228 | } 229 | module.exports = ERC20ABI; 230 | -------------------------------------------------------------------------------- /scripts/generateGoBindings.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const path = require('path') 3 | const { exec } = require("child_process") 4 | 5 | const abis = fs.readdirSync(path.resolve(__dirname, '../abi')) 6 | 7 | abis.forEach((abi) => { 8 | if (!abi.match(".json")) 9 | return 10 | const source = path.resolve(__dirname, '../abi', abi) 11 | const goName = abi.replace(".json", "") 12 | const destination = path.resolve(__dirname, '../abigo', goName) 13 | 14 | const cmd = `abigen --abi ${source} --pkg abigo --type ${goName} --out ${destination}.go` 15 | exec(cmd, (error, stdout, stderr) => { 16 | if (error) { 17 | console.log(`error: ${error.message}`); 18 | return; 19 | } 20 | if (stderr) { 21 | console.log(`stderr: ${stderr}`); 22 | return; 23 | } 24 | console.log(`${abi} -> ${goName}.go`); 25 | }); 26 | }) 27 | -------------------------------------------------------------------------------- /scripts/mintToken.js: -------------------------------------------------------------------------------- 1 | const { BN } = require('@openzeppelin/test-helpers'); 2 | 3 | const SwingbyToken = artifacts.require("SwingbyToken"); 4 | 5 | module.exports = async function (done) { 6 | // await deployer.deploy(LPToken) 7 | try { 8 | const token = await SwingbyToken.at("0x423fa1c32541b3d9fc3690e15392185753d44fad") 9 | console.log("token:", token.address) 10 | let amount = new BN(1000000).mul(new BN(10).pow(new BN(18))) 11 | await token.mint(process.env.OWNER, amount) 12 | } catch (err) { 13 | console.log(err) 14 | } 15 | done() 16 | }; 17 | -------------------------------------------------------------------------------- /scripts/moveLPTOwner.js: -------------------------------------------------------------------------------- 1 | 2 | const LPToken = artifacts.require("LPToken"); 3 | const SwapContract = artifacts.require("SwapContract"); 4 | 5 | module.exports = async function (done) { 6 | // await deployer.deploy(LPToken) 7 | try { 8 | const lpToken = await LPToken.deployed() 9 | const swap = await SwapContract.deployed() 10 | await lpToken.transferOwnership(swap.address) 11 | } catch (err) { 12 | console.log(err) 13 | } 14 | done() 15 | }; 16 | -------------------------------------------------------------------------------- /scripts/moveSCOwner.js: -------------------------------------------------------------------------------- 1 | 2 | const LPToken = artifacts.require("LPToken"); 3 | const SwapContract = artifacts.require("SwapContract"); 4 | 5 | module.exports = async function (done) { 6 | // await deployer.deploy(LPToken) 7 | try { 8 | const swap = await SwapContract.deployed() 9 | console.log("SwapContract:", swap.address) 10 | await swap.transferOwnership(process.env.TSS) 11 | } catch (err) { 12 | console.log(err) 13 | } 14 | done() 15 | }; 16 | -------------------------------------------------------------------------------- /scripts/paraswap.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios'); 2 | const { BigNumber, Ethers } = require('ethers') 3 | 4 | //call the class with this 5 | const paraURL = "https://apiv4.paraswap.io/v2" 6 | const paraV5 = "https://apiv5.paraswap.io/" 7 | 8 | class ParaSwap { 9 | 10 | constructor(apiURL, version) { 11 | this.apiURL = apiURL 12 | this.version = version 13 | this.referrer = 'SkyPools' 14 | } 15 | 16 | async getTokens(networkID){ 17 | if(this.version == 5){ 18 | const requestURL = `${this.apiURL}/tokens/${networkID}` 19 | 20 | const {data} = await axios.get(requestURL).catch(e => { 21 | if (e.response != undefined) { 22 | console.log("ERROR RESPONSE: ", e.response.data) 23 | } else { console.log("ERROR: ", e) } 24 | }) 25 | return {data} 26 | } 27 | } 28 | 29 | async getPrice(from, to, srcAmount, network) { 30 | if (this.version == 4) { 31 | try { 32 | const requestURL = 33 | `${this.apiURL}/prices/?from=${from.address}&to=${to.address}` + 34 | `&amount=${srcAmount}&fromDecimals=${from.decimals}&toDecimals` + 35 | `=${to.decimals}&side=SELL&network=${network}` 36 | 37 | const { data } = await axios.get(requestURL, { 38 | headers: { 39 | 'X-Partner': this.referrer, 40 | }, 41 | }).catch(e => { 42 | if (e.response != undefined) { 43 | console.log("ERROR RESPONSE: ", e.response.data) 44 | } else { console.log("ERROR: ", e) } 45 | }) 46 | return { 47 | price: data.priceRoute.destAmount, 48 | payload: data.priceRoute, 49 | } 50 | } catch (e) { 51 | throw new Error( 52 | `Paraswap unable to fetch price ${from.address} ${to.address} ${network} ${e.message}` 53 | ) 54 | } 55 | } else if (this.version == 5) { 56 | try { 57 | const requestURL = 58 | `${this.apiURL}/prices/?srcToken=${from.address}&destToken=${to.address}` + 59 | `&amount=${srcAmount}&srcDecimals=${from.decimals}&destDecimals` + 60 | `=${to.decimals}&side=SELL&network=${network}&maxImpact=100` 61 | //PICK WHICH CONTRACT METHODS TO INCLUDE 62 | //+ `&includeContractMethods=swapOnUniswapFork` 63 | //+ `&includeContractMethods=swapOnUniswap` 64 | //+ `&includeContractMethods=simpleSwap` 65 | + `&includeContractMethods=swapOnUniswap,swapOnUniswapFork` 66 | 67 | const { data } = await axios.get(requestURL, { 68 | headers: { 69 | 'partner': this.referrer, 70 | }, 71 | }).catch(e => { 72 | if (e.response != undefined) { 73 | console.log("ERROR RESPONSE: ", e.response.data) 74 | } else { console.log("ERROR: ", e) } 75 | }) 76 | return { 77 | price: data.priceRoute.destAmount, 78 | payload: data.priceRoute, 79 | } 80 | } catch (e) { 81 | throw new Error( 82 | `Paraswap unable to fetch price ${from.address} ${to.address} ${network} ${e.message}` 83 | ) 84 | } 85 | } 86 | 87 | } 88 | 89 | 90 | async buildTransaction( 91 | pricePayload, 92 | from, 93 | to, 94 | srcAmount, 95 | minDestAmount, 96 | network, 97 | userAddress, 98 | onlyParams 99 | ) { 100 | if (this.version == 4) { 101 | const requestURL = `${this.apiURL}/transactions/${network}?skipChecks=true&onlyParams=${onlyParams}`; 102 | const requestData = { 103 | toDecimals: to.decimals, 104 | fromDecimals: from.decimals, 105 | referrer: this.referrer, 106 | userAddress: userAddress, 107 | destAmount: minDestAmount, 108 | priceRoute: pricePayload, 109 | srcAmount: srcAmount, 110 | destToken: to.address, 111 | srcToken: from.address, 112 | receiver: userAddress 113 | } 114 | console.log("destAmount", minDestAmount) 115 | let data = "No Response" 116 | await axios.post( 117 | requestURL, 118 | requestData 119 | ).then(response => { 120 | //console.log("RESPONSE: ", response) 121 | data = response 122 | }).catch(e => { 123 | if (e.response != undefined) { 124 | console.log("ERROR RESPONSE: ", e.response) 125 | data = e.response 126 | } else { console.log("ERROR: ", e) } 127 | }) 128 | return data 129 | } else if (this.version == 5) { 130 | const requestURL = `${this.apiURL}/transactions/${network}?skipChecks=true&onlyParams=${onlyParams}`; 131 | const requestData = { 132 | destDecimals: to.decimals, 133 | srcDecimals: from.decimals, 134 | partner: this.referrer, 135 | userAddress: userAddress, 136 | //destAmount: minDestAmount, 137 | slippage: 5000, //50% -> prevents issues with EXPECTED_AMOUNT_GREATER_THAN_MAX_IMPACT 138 | priceRoute: pricePayload, 139 | srcAmount: srcAmount, 140 | destToken: to.address, 141 | srcToken: from.address, 142 | receiver: userAddress 143 | } 144 | let data = "No Response" 145 | await axios.post( 146 | requestURL, 147 | requestData 148 | ).then(response => { 149 | //console.log("RESPONSE: ", response) 150 | data = response 151 | }).catch(e => { 152 | if (e.response != undefined) { 153 | console.log("ERROR RESPONSE: ", e.response) 154 | data = e.response 155 | } else { console.log("ERROR: ", e) } 156 | }) 157 | return data 158 | } 159 | } 160 | 161 | } 162 | 163 | module.exports = ParaSwap; -------------------------------------------------------------------------------- /scripts/removeFloat.js: -------------------------------------------------------------------------------- 1 | 2 | const { BN, constants } = require('@openzeppelin/test-helpers'); 3 | const { ZERO_ADDRESS } = constants 4 | const SwapContract = artifacts.require("SwapContract"); 5 | const LPToken = artifacts.require("LPToken"); 6 | 7 | module.exports = async function (done) { 8 | // await deployer.deploy(LPToken) 9 | try { 10 | const swap = await SwapContract.deployed() 11 | // send 0.1 BTC as float 12 | let amount = new BN(3231122121817231).mul(new BN(10).pow(new BN(1))) 13 | //let amount = new BN(3933663654516931) 14 | let to = process.env.TO 15 | let AmountLP2 = "0x" + web3.utils.padLeft(amount.toString('hex') + to.slice(2), 64) 16 | let minerFees = 0 17 | let txid = "0x1c12143203aa1f42cdf1b1acee5b1b1c1fedc144cb309a3bf5edcffafb0ac731" 18 | let btct = await swap.BTCT_ADDR() 19 | let lptAddr = await swap.lpToken() 20 | 21 | const lpt = await LPToken.at(lptAddr) 22 | const deposit = await lpt.transfer(swap.address, amount) 23 | //console.log('max', amountMAXBTCfloatLP.toString()) 24 | await swap.recordOutcomingFloat(ZERO_ADDRESS, AmountLP2, minerFees, deposit.tx) 25 | } catch (err) { 26 | console.log(err) 27 | } 28 | done() 29 | }; 30 | -------------------------------------------------------------------------------- /scripts/sbBTCchecks.js: -------------------------------------------------------------------------------- 1 | const { ZERO_ADDRESS } = require("@openzeppelin/test-helpers/src/constants"); 2 | const { ethers } = require("hardhat"); 3 | BN = require('bn.js') 4 | /********************************************************************* 5 | * 6 | * Boiler Plate script to deploy 7 | * 8 | * July 28, 2021 9 | * 10 | * Deploy with: 11 | * npx hardhat run ./scripts/deploy.js --network development || npx hardhat run ./scripts/deploy.js --network hardhat 12 | * There are still some errors with the above 13 | */ 14 | async function main() { 15 | [...addrs] = await ethers.getSigners(); 16 | //console.log(addrs.map((s) => s.address)) 17 | const swapContrat = '0x9e6BA6e811665849f03f56C1f22a8894AEbb3993' 18 | const sbBTC_Pool = '0xD60126017fDf906668Cfe5327c566C65e7f061bA' 19 | const barnContract = '0x009cc14ce70b2E667984C2276490d56ae3234c43' 20 | const SwapContractFactory = await ethers.getContractFactory("SwapContract"); 21 | const sbBTCFactory = await ethers.getContractFactory("sbBTCPool"); 22 | const barnFactory = await ethers.getContractFactory("LPToken"); 23 | const swap = await SwapContractFactory.attach(swapContrat); 24 | const sbBTCP = await sbBTCFactory.attach(sbBTC_Pool) 25 | const barn = await barnFactory.attach(barnContract) 26 | 27 | nodes = [] 28 | var skipped = [] 29 | 30 | //console.log(addrs) 31 | 32 | for (i = 0; i < 10; i++) { 33 | nodes.push({ 34 | address: addrs[i].address, 35 | claim: sbBTCP.connect(addrs[i]).callStatic.claim(), 36 | barn: barn.balanceOf(addrs[i].address) 37 | }) 38 | } 39 | var sum = 0; 40 | const claimed = await Promise.allSettled(nodes.map((s) => s.claim)) 41 | const barnBalance = await Promise.allSettled(nodes.map((s) => s.barn)) 42 | const nodeList = [] 43 | claimed.forEach((s, i) => { 44 | if (s.status == "fulfilled") { 45 | nodeList.push({ address: nodes[i].address, amount: (s.value / 1e8), barnBalance: barnBalance[i].value / 1e18 }) 46 | sum += s.value / 1e8 47 | } else { 48 | skipped.push(nodes[i].address) 49 | } 50 | }) 51 | const sorted = nodeList.sort(function (a, b) { 52 | return b.amount - a.amount 53 | }) 54 | console.log("sum -------------------------------------- ", sum, "time:", new Date(), "contract:", sbBTCP.address) 55 | 56 | sorted.forEach(async (s) => { 57 | console.log(`address: ${s.address} amount: ${s.amount.toFixed(8)}, bal: ${s.barnBalance.toFixed(8)}`) 58 | }) 59 | console.log("skipped: ", skipped) 60 | } 61 | main() 62 | .then(() => process.exit(0)) 63 | .catch((error) => { 64 | console.error(error); 65 | process.exit(1); 66 | }); 67 | -------------------------------------------------------------------------------- /scripts/showNodes.js: -------------------------------------------------------------------------------- 1 | 2 | const { BN, constants } = require('@openzeppelin/test-helpers'); 3 | const { web3 } = require('@openzeppelin/test-helpers/src/setup'); 4 | const { ZERO_ADDRESS } = constants 5 | const SwapContract = artifacts.require("SwapContract"); 6 | 7 | module.exports = async function (done) { 8 | // await deployer.deploy(LPToken) 9 | try { 10 | const swap = await SwapContract.at(process.env.WALLET) 11 | const res = await swap.getActiveNodes.call({ gas: 500000, gasPrice: 1 * 10 ** 9 }) 12 | const val = new BN(1).mul(new BN(10).pow(new BN(8))) 13 | const result = res.map((stake) => { 14 | const amount = web3.utils.hexToNumber(stake.slice(0, 26)) 15 | return { 16 | amount: amount / 1e8, 17 | address: "0x" + stake.slice(26, stake.length) 18 | } 19 | }).sort(function (a, b) { 20 | return b.amount - a.amount; 21 | }); 22 | console.log(result) 23 | } catch (err) { 24 | console.log(err) 25 | } 26 | done() 27 | }; 28 | -------------------------------------------------------------------------------- /scripts/swapBTC2WBTC.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require("hardhat"); 2 | BN = require('bn.js') 3 | const { BigNumber } = require('ethers'); 4 | 5 | /********************************************************************* 6 | * 7 | * Boiler Plate script to deploy 8 | * 9 | * July 28, 2021 10 | * 11 | * Deploy with: 12 | * npx hardhat run ./scripts/deploy.js --network development || npx hardhat run ./scripts/deploy.js --network hardhat 13 | * There are still some errors with the above 14 | */ 15 | async function main() { 16 | const swapContrat = '0x9e6BA6e811665849f03f56C1f22a8894AEbb3993' 17 | const to = '0x63d9f6A25ddD2c586F4441065Ce7C8412fbBB91e' 18 | const SwapContractFactory = await ethers.getContractFactory("SwapContract"); 19 | const swap = await SwapContractFactory.attach(swapContrat); 20 | 21 | // send 0.1 BTC as float 22 | minerFees = new BigNumber.from(30000) 23 | 24 | //prep to collectSwapFeesForBTC 25 | let swapFeesBPS = new BigNumber.from(20); 26 | //let swapAmount = new BigNumber.from(1).mul(new BigNumber.from(10).pow(decimals)) 27 | 28 | let swapAmount = new BigNumber.from(10000000) //.1 BTC 29 | let swapFees = swapAmount.mul(swapFeesBPS).div(new BigNumber.from(10000)) 30 | //let rewardsAmount = swapFees.sub(minerFees) 31 | let incomingAmount = swapAmount.add(swapFees) //100200000 sats = 1.002 BTC 32 | let spenders = [to] 33 | let amounts = [incomingAmount] 34 | 35 | let btct = await swap.BTCT_ADDR() 36 | const tx = await swap.singleTransferERC20( 37 | btct, 38 | to, 39 | swapAmount, 40 | swapAmount, 41 | swapFees, 42 | [], 43 | ) 44 | console.log(tx.hash); 45 | } 46 | 47 | main() 48 | .then(() => process.exit(0)) 49 | .catch((error) => { 50 | console.error(error); 51 | process.exit(1); 52 | }); -------------------------------------------------------------------------------- /scripts/swapWBTC2BTC.js: -------------------------------------------------------------------------------- 1 | const { ethers } = require("hardhat"); 2 | BN = require('bn.js') 3 | const { BigNumber } = require('ethers'); 4 | 5 | /********************************************************************* 6 | * 7 | * Boiler Plate script to deploy 8 | * 9 | * July 28, 2021 10 | * 11 | * Deploy with: 12 | * npx hardhat run ./scripts/deploy.js --network development || npx hardhat run ./scripts/deploy.js --network hardhat 13 | * There are still some errors with the above 14 | */ 15 | async function main() { 16 | const swapContrat = '0x9e6BA6e811665849f03f56C1f22a8894AEbb3993' 17 | const to = '0x63d9f6A25ddD2c586F4441065Ce7C8412fbBB91e' 18 | const SwapContractFactory = await ethers.getContractFactory("SwapContract"); 19 | const swap = await SwapContractFactory.attach(swapContrat); 20 | 21 | // send 0.1 BTC as float 22 | minerFees = new BigNumber.from(30000) 23 | 24 | //prep to collectSwapFeesForBTC 25 | let swapFeesBPS = new BigNumber.from(20); 26 | //let swapAmount = new BigNumber.from(1).mul(new BigNumber.from(10).pow(decimals)) 27 | 28 | let swapAmount = new BigNumber.from(10000000) //.1 BTC 29 | let swapFees = swapAmount.mul(swapFeesBPS).div(new BigNumber.from(10000)) 30 | //let rewardsAmount = swapFees.sub(minerFees) 31 | let incomingAmount = swapAmount.add(swapFees) //100200000 sats = 1.002 BTC 32 | let spenders = [to] 33 | let amounts = [incomingAmount] 34 | 35 | const tx = await swap.collectSwapFeesForBTC( 36 | swapAmount, 37 | minerFees, 38 | swapFees, 39 | spenders, 40 | amounts, 41 | ) 42 | console.log(tx.hash); 43 | } 44 | 45 | main() 46 | .then(() => process.exit(0)) 47 | .catch((error) => { 48 | console.error(error); 49 | process.exit(1); 50 | }); -------------------------------------------------------------------------------- /scripts/testnet.js: -------------------------------------------------------------------------------- 1 | const { BigNumber } = require("@ethersproject/contracts/node_modules/@ethersproject/bignumber") 2 | const hre = require("hardhat") 3 | const { Ethers } = require('ethers') 4 | const ParaSwap = require('../scripts/paraswap.js') 5 | const paraV5 = "https://apiv5.paraswap.io" 6 | const paraswap = new ParaSwap(paraV5, 5) 7 | const ropsten = 3 //ropsten 8 | const mainnet = 1 9 | const swapAddress = '0xf73D63C3eB97389cB5A28C4aD5e8AC428cb16417' 10 | const swapABI = require('../abi/SwapContract.json') 11 | const { default: Web3 } = require('web3'); 12 | 13 | //npx hardhat run testnet.js 14 | 15 | const Tokens = { 16 | [ropsten]: { 17 | WETH: { 18 | address: '0xc778417e063141139fce010982780140aa0cd5ab', 19 | decimals: 18 20 | }, 21 | WBTC: { 22 | //address: '0x442be68395613bdcd19778e761f03261ec46c06d', 23 | address: '0x7cb2eac36b4bb7c36640f32e806d33e474d1d427', 24 | decimals: 8 25 | }, 26 | DAI: { 27 | address: '0xaD6D458402F60fD3Bd25163575031ACDce07538D', 28 | decimals: 18 29 | }, 30 | UNI: { 31 | address: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984', 32 | decimals: 18 33 | }, 34 | }, 35 | [mainnet]: { 36 | ETH: { 37 | address: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', 38 | decimals: 18, 39 | }, 40 | WETH: { 41 | address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', 42 | decimals: 18 43 | }, 44 | USDC: { 45 | address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', 46 | decimals: 6, 47 | }, 48 | MATIC: { 49 | address: '0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0', 50 | decimals: 18, 51 | }, 52 | WBTC: { 53 | address: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', 54 | decimals: 8 55 | }, 56 | UNI: { 57 | address: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984', 58 | decimals: 18 59 | }, 60 | COMP: { 61 | address: '0xc00e94cb662c3520282e6f5717214004a7f26888', 62 | decimals: 18 63 | }, 64 | MKR: { 65 | address: '0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2', 66 | decimals: 18 67 | }, 68 | SWINGBY: { 69 | address: '0x8287c7b963b405b7b8d467db9d79eec40625b13a', 70 | decimals: 18 71 | } 72 | }, 73 | } 74 | 75 | const srcAmountBTC = "10000000"//0.1 BTC //USE FOR FLOW 1 76 | const srcAmountETH = "1000000000000000000"//1 ETHER //USE FOR FLOW 2 77 | const smallSrcAmountETH = "100000000000000000"//0.1 ETHER //USE FOR FLOW 2 78 | 79 | const giantAmountFlow2 = "15000000000000000000" // 15 ETH 80 | 81 | 82 | 83 | //const srcAmount = "147618252344340533" 84 | //UNI Amount: 147618252344340533 85 | //UNI Address: 0x1f9840a85d5af5bf1d1762f925bdaddc4201f984 86 | 87 | 88 | async function main() { 89 | let data 90 | let getPrice = await paraswap.getPrice( 91 | Tokens[ropsten]['WETH'], // From token - CHANGE THIS 92 | Tokens[ropsten]['WBTC'], // To token - CHANGE THIS 93 | srcAmountETH, //Change this depending on flow 1 vs flow 2 94 | ropsten 95 | ) 96 | 97 | //console.log(getPrice) 98 | 99 | const slippage = (decimals) => { 100 | return new BigNumber.from(3).mul(new BigNumber.from(10).pow(decimals - 2)).toString() //Format ERC20 - 0.05 101 | } 102 | 103 | let decimals = Tokens[ropsten]['WETH'].decimals 104 | let minDestAmount = new BigNumber.from(getPrice.price).sub(slippage(decimals)) 105 | 106 | //POST request - build TX data to send to contract 107 | const txRequest = await paraswap.buildTransaction( 108 | getPrice.payload, //data from GET request 109 | Tokens[ropsten]['WETH'], // From token - CHANGE THIS 110 | Tokens[ropsten]['WBTC'], // To token - CHANGE THIS 111 | srcAmountETH, //Change this depending on flow 1 vs flow 2 112 | minDestAmount.toString(), //this param is not used for paraswap V5 anymore, redundant 113 | ropsten, 114 | "0x202CCe504e04bEd6fC0521238dDf04Bc9E8E15aB", //SWAP contract - flow 2 simpleSwap - uniswap functions don't care about this param 115 | //"0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC", //user1.address - Flow 1 simpleSwap 116 | true //only params - true for contract -> contract | false for standard transaction object 117 | ) 118 | data = txRequest.data //params to execute transaction contract -> contract 119 | const output = txRequest.config.data 120 | const { parse } = require('json-parser') 121 | const parsedOutput = parse(output) 122 | const contractMethod = parsedOutput.priceRoute.contractMethod 123 | 124 | 125 | console.log("Recomended Contract Method:", contractMethod) 126 | //console.log(data) 127 | 128 | if (contractMethod == "simpleSwap") { 129 | console.log(`Getting data for ${contractMethod}`) 130 | const dataArray = [ 131 | data[0].fromToken, 132 | data[0].toToken, 133 | data[0].fromAmount, 134 | data[0].toAmount, 135 | data[0].expectedAmount, 136 | data[0].callees, 137 | data[0].exchangeData, 138 | data[0].startIndexes, 139 | data[0].values, 140 | data[0].beneficiary, 141 | data[0].partner, 142 | data[0].feePercent, 143 | data[0].permit, 144 | data[0].deadline, 145 | data[0].uuid 146 | ] 147 | console.log(dataArray) 148 | } else if (contractMethod == "swapOnUniswap") { 149 | console.log(`Getting data for ${contractMethod}`) 150 | console.log(data) 151 | } else if (contractMethod == "swapOnUniswapFork") { 152 | console.log(`Getting data for ${contractMethod}`) 153 | console.log(data) 154 | } 155 | 156 | 157 | 158 | /** 159 | //megaSwap 160 | let routeArray = [ 161 | data[0].path[0].path[0].adapters[0].route[0].index, 162 | data[0].path[0].path[0].adapters[0].route[0].targetExchange, 163 | data[0].path[0].path[0].adapters[0].route[0].percent, 164 | data[0].path[0].path[0].adapters[0].route[0].payload, 165 | data[0].path[0].path[0].adapters[0].route[0].networkFee 166 | ] 167 | let pathArray = [ 168 | data[0].path[0].fromAmountPercent, 169 | [ 170 | data[0].path[0].path[0].to, 171 | data[0].path[0].path[0].totalNetworkFee, 172 | [ //adapters 173 | data[0].path[0].path[0].adapters[0].adapter, 174 | data[0].path[0].path[0].adapters[0].percent, 175 | data[0].path[0].path[0].adapters[0].networkFee, 176 | routeArray 177 | ] 178 | ] 179 | ] 180 | const megaDataArray = [ 181 | data[0].fromToken, 182 | data[0].fromAmount, 183 | data[0].toAmount, 184 | data[0].expectedAmount, 185 | data[0].beneficiary, 186 | pathArray, 187 | data[0].partner, 188 | data[0].feePercent, 189 | data[0].permit, 190 | data[0].deadline, 191 | data[0].uuid 192 | ] 193 | 194 | /** 195 | console.log(dataArray) 196 | 197 | console.log("PATH BELOW") 198 | console.log(pathArray) 199 | 200 | console.log("ROUTE BELOW") 201 | console.log(routeArray) 202 | */ 203 | 204 | 205 | 206 | //console.log(data[0].path[0].path[0].adapters[0].route[0].targetExchange) 207 | 208 | //console.log(dataArray) 209 | //console.log(data[0].path) 210 | //console.log(data[0].path[0].path) 211 | //console.log(data[0].path[0].path[0].adapters) 212 | //console.log(data[0].path[0].path[0].adapters[0].route) 213 | 214 | } 215 | 216 | 217 | main() 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | //SWAP: 0xf73D63C3eB97389cB5A28C4aD5e8AC428cb16417 237 | 238 | 239 | //DAI Amount: 548824612259226186639 240 | //DAI Address: 0xaD6D458402F60fD3Bd25163575031ACDce07538D 241 | 242 | //UNI Amount: 147618252344340533 243 | //UNI Address: 0x1f9840a85d5af5bf1d1762f925bdaddc4201f984 -------------------------------------------------------------------------------- /scripts/transferOwner.js: -------------------------------------------------------------------------------- 1 | 2 | const SwingbyToken = artifacts.require("SwingbyToken"); 3 | 4 | module.exports = async function (done) { 5 | // await deployer.deploy(LPToken) 6 | try { 7 | const token = await SwingbyToken.at("0xbd6c7cdf51d143b62bb5e5141313a6d41ea3dd54") 8 | console.log("token:", token.address) 9 | await token.transferOwnership(process.env.OWNER) 10 | } catch (err) { 11 | console.log(err) 12 | } 13 | done() 14 | }; 15 | -------------------------------------------------------------------------------- /test/testLPToken.js: -------------------------------------------------------------------------------- 1 | const { BN, constants, expectEvent, expectRevert } = require('@openzeppelin/test-helpers'); 2 | const { expect, assert } = require('chai'); 3 | const { BigNumber } = require('ethers'); 4 | const { ZERO_ADDRESS } = constants; 5 | const TOKEN_DECIMALS = process.env.TOKEN_DECIMALS || 18 6 | 7 | 8 | //Web3 init 9 | //const LPToken = artifacts.require('LPToken'); 10 | //const SwapContract = artifacts.require('SwapContract'); 11 | describe("Contract: LPToken", () => { 12 | 13 | 14 | let LPTokenFactory, sender, receiver, accounts 15 | 16 | let value, token, mintValue 17 | 18 | const name = "Swingby BTC LP Token"; 19 | const symbol = 'sbBTC'; 20 | 21 | beforeEach(async () => { 22 | // The bundled BN library is the same one web3 uses under the hood 23 | [sender, receiver, ...addrs] = await ethers.getSigners(); 24 | //this contains all of the account objects, access address string -> accounts[n].address 25 | accounts = [sender, receiver, ...addrs] 26 | 27 | LPTokenFactory = await ethers.getContractFactory("LPToken"); 28 | 29 | value = new BigNumber.from(1) 30 | 31 | token = await LPTokenFactory.deploy(TOKEN_DECIMALS); 32 | 33 | mintValue = new BigNumber.from(500).mul(new BigNumber.from(10).pow(new BigNumber.from(TOKEN_DECIMALS))) 34 | 35 | await token.mint(sender.address, mintValue) 36 | }) 37 | 38 | // You can nest describe calls to create subsections. 39 | describe("LPToken functions", () => { 40 | 41 | 42 | it('has a name', async () => { 43 | expect(await token.name()).to.equal(name) 44 | }); 45 | it('has a symbol', async () => { 46 | expect(await token.symbol()).to.equal(symbol); 47 | }); 48 | it('has the right decimals', async () => { 49 | decimals = await token.decimals() 50 | expect(new BigNumber.from(decimals)).equal(new BigNumber.from(TOKEN_DECIMALS)); 51 | }); 52 | it('reverts when minting tokens from not owner', async () => { 53 | // Conditions that trigger a require statement can be precisely tested\ 54 | await expectRevert( 55 | token.connect(receiver).mint(receiver.address, value), 56 | 'Ownable: caller is not the owner', 57 | ); 58 | }); 59 | it('reverts when transferring tokens to the zero address', async () => { 60 | // Conditions that trigger a require statement can be precisely tested 61 | await expectRevert( 62 | token.connect(sender).transfer(constants.ZERO_ADDRESS, value), 63 | 'ERC20: transfer to the zero address', 64 | ); 65 | }); 66 | it('emits a Transfer event on successful transfers', async () => { 67 | let tx = await token.connect(sender).transfer(receiver.address, value); 68 | let receipt = await tx.wait(); 69 | const data = receipt.events[0].args 70 | //console.log(data);//data emitted from Transfer Event 71 | 72 | assert.equal(receipt.events[0].event, 'Transfer', "Emits correct event") 73 | assert.equal(data.from, sender.address) 74 | assert.equal(data.to, receiver.address) 75 | assert.equal(data.value._hex, value._hex) 76 | 77 | 78 | }); 79 | it('updates balances on successful transfers', async () => { 80 | await token.connect(sender).transfer(receiver.address, value) 81 | 82 | balanceOfReceiver = await token.balanceOf(receiver.address) 83 | expect(new BigNumber.from(balanceOfReceiver.sub(value))).equal('0') 84 | }); 85 | it('emits a Burn event on successful burning', async () => { 86 | let tx = await token.connect(sender).burn(mintValue); 87 | let receipt = await tx.wait(); 88 | const data = receipt.events[0].args 89 | //console.log(data);//data emitted from Transfer Event 90 | 91 | assert.equal(receipt.events[0].event, 'Transfer', "Emits correct event") 92 | assert.equal(data.from, sender.address) 93 | assert.equal(data.to, ZERO_ADDRESS) 94 | assert.equal(data.value._hex, mintValue._hex) 95 | }); 96 | 97 | 98 | 99 | 100 | }); 101 | }); 102 | -------------------------------------------------------------------------------- /test/testSwapContractFactory.js: -------------------------------------------------------------------------------- 1 | const { constants, expectEvent, expectRevert } = require('@openzeppelin/test-helpers'); 2 | const { expect, assert } = require('chai'); 3 | const { BigNumber } = require('ethers'); 4 | const { ZERO_ADDRESS } = constants; 5 | const TOKEN_DECIMALS = process.env.TOKEN_DECIMALS || 18 6 | 7 | 8 | //Web3 init 9 | //const LPToken = artifacts.require('LPToken'); 10 | //const SwapContract = artifacts.require('SwapContract'); 11 | describe("Contract: SwapFactory", () => { 12 | 13 | 14 | let LPTokenFactory, SwapContractFactory, SwapContract, factory, sender, receiver, accounts 15 | 16 | let value, btctTest, mintValue, btctDecimals 17 | 18 | 19 | beforeEach(async () => { 20 | // The bundled BN library is the same one web3 uses under the hood 21 | [sender, receiver, ...addrs] = await ethers.getSigners(); 22 | //this contains all of the account objects, access address string -> accounts[n].address 23 | accounts = [sender, receiver, ...addrs] 24 | 25 | LPToken = await ethers.getContractFactory("LPToken"); 26 | SwapContractFactory = await ethers.getContractFactory("SwapContractFactory"); 27 | SwapContract = await ethers.getContractFactory("SwapContract"); 28 | 29 | value = new BigNumber.from(1) 30 | 31 | btctTest = await LPToken.deploy(TOKEN_DECIMALS) 32 | 33 | btctDecimals = await btctTest.decimals() 34 | 35 | mintValue = new BigNumber.from(500).mul(new BigNumber.from(10).pow(new BigNumber.from(TOKEN_DECIMALS))) 36 | 37 | factory = await SwapContractFactory.deploy() 38 | 39 | }) 40 | 41 | // You can nest describe calls to create subsections. 42 | describe("Deploy New Contracts", () => { 43 | it('checks the owner after deployment', async () => { 44 | const sc = await factory.connect(receiver).deployNewContracts(receiver.address, btctTest.address, TOKEN_DECIMALS, 0) 45 | const receipt = await sc.wait() 46 | 47 | //get existing contract address -- condensed to separate consts for readability 48 | const lpTokenAddress = receipt.events[receipt.events.length - 1].args.lpToken 49 | const swapContractAddress = receipt.events[receipt.events.length - 1].args.swapContract 50 | 51 | const newLPToken = await LPToken.attach(lpTokenAddress) //equivilant to truffle .at() method 52 | const newSwapContract = await SwapContract.attach(swapContractAddress) 53 | 54 | 55 | expect(await newLPToken.getOwner()).to.equal(newSwapContract.address) 56 | expect(await newSwapContract.owner()).to.equal(receiver.address) 57 | 58 | 59 | }); 60 | }); 61 | }); 62 | -------------------------------------------------------------------------------- /truffle-config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Use this file to configure your truffle project. It's seeded with some 3 | * common settings for different networks and features like migrations, 4 | * compilation and testing. Uncomment the ones you need or modify 5 | * them to suit your project as necessary. 6 | * 7 | * More information about configuration can be found at: 8 | * 9 | * trufflesuite.com/docs/advanced/configuration 10 | * 11 | * To deploy via Infura you'll need a wallet provider (like @truffle/hdwallet-provider) 12 | * to sign your transactions before they're sent to a remote public node. Infura accounts 13 | * are available for free at: infura.io/register. 14 | * 15 | * You'll also need a mnemonic - the twelve word phrase the wallet uses to generate 16 | * public/private key pairs. If you're publishing your code to GitHub make sure you load this 17 | * phrase from a file you've .gitignored so it doesn't accidentally become public. 18 | * 19 | */ 20 | require('dotenv').config(); 21 | const mnemonic = [process.env.PRIVATE_KEYS] || "not found" 22 | console.log(mnemonic) 23 | //const HDWalletProvider = require('@truffle/hdwallet-provider'); 24 | const HDWalletProvider = require('truffle-hdwallet-provider-privkey'); 25 | 26 | // const infuraKey = "fj4jll3k....."; 27 | // 28 | // const fs = require('fs'); 29 | //const mnemonic = process.env.SEED 30 | 31 | 32 | module.exports = { 33 | /** 34 | * Networks define how you connect to your ethereum client and let you set the 35 | * defaults web3 uses to send transactions. If you don't specify one truffle 36 | * will spin up a development blockchain for you on port 9545 when you 37 | * run `develop` or `test`. You can ask a truffle command to use a specific 38 | * network from the command line, e.g 39 | * 40 | * $ truffle test --network 41 | */ 42 | 43 | networks: { 44 | // Useful for testing. The `development` name is special - truffle uses it by default 45 | // if it's defined here and no other network is specified at the command line. 46 | // You should run a client (like ganache-cli, geth or parity) in a separate terminal 47 | // tab if you use this network and you must also set the `host`, `port` and `network_id` 48 | // options below to some value. 49 | // 50 | development: { 51 | host: "127.0.0.1", // Localhost (default: none) 52 | port: 8545, // Standard Ethereum port (default: none) 53 | network_id: "*", // Any network (default: none) 54 | }, 55 | // Another network with more advanced options... 56 | // advanced: { 57 | // port: 8777, // Custom port 58 | // network_id: 1342, // Custom network 59 | // gas: 8500000, // Gas sent with each transaction (default: ~6700000) 60 | // gasPrice: 20000000000, // 20 gwei (in wei) (default: 100 gwei) 61 | // from:
, // Account to send txs from (default: accounts[0]) 62 | // websockets: true // Enable EventEmitter interface for web3 (default: false) 63 | // }, 64 | // Useful for deploying to a public network. 65 | // NB: It's important to wrap the provider as a function. 66 | goerli: { 67 | provider: () => new HDWalletProvider(mnemonic, `https://goerli.infura.io/v3/f35c2a4f3d0941a38a3edb62ed10c847`), 68 | network_id: 5, // Ropsten's id 69 | gas: 5500000, // Ropsten has a lower block limit than mainnet 70 | confirmations: 2, // # of confs to wait between deployments. (default: 0) 71 | timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50) 72 | skipDryRun: true, // Skip dry run before migrations? (default: false for public nets ) 73 | gasPrice: 53000000000 74 | }, 75 | 76 | ropsten: { 77 | provider: function () { 78 | return new HDWalletProvider( 79 | mnemonic, 80 | `https://eth-ropsten.alchemyapi.io/v2/5EGdI7OUE9ptMFggrLzsM2dDpBYPMujp` 81 | ) 82 | }, 83 | network_id: 3, // Ropsten's id 84 | gas: 8000000, // Ropsten has a lower block limit than mainnet 85 | confirmations: 2, // # of confs to wait between deployments. (default: 0) 86 | timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50) 87 | skipDryRun: true, // Skip dry run before migrations? (default: false for public nets ) 88 | gasPrice: 53000000000 89 | }, 90 | mainnet: { 91 | provider: () => new HDWalletProvider(mnemonic, `https://mainnet.infura.io/v3/f35c2a4f3d0941a38a3edb62ed10c847`), 92 | network_id: 1, // Ropsten's id 93 | gas: 3000000, // Ropsten has a lower block limit than mainnet 94 | confirmations: 2, // # of confs to wait between deployments. (default: 0) 95 | timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50) 96 | skipDryRun: true, // Skip dry run before migrations? (default: false for public nets ) 97 | gasPrice: 93000000000 98 | }, 99 | bsc_testnet: { 100 | provider: () => new HDWalletProvider(mnemonic, `https://data-seed-prebsc-1-s1.binance.org:8545`), 101 | network_id: 97, // Ropsten's id 102 | gas: 7500000, // Ropsten has a lower block limit than mainnet 103 | confirmations: 2, // # of confs to wait between deployments. (default: 0) 104 | timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50) 105 | skipDryRun: true, // Skip dry run before migrations? (default: false for public nets ) 106 | gasPrice: 10000000000 107 | }, 108 | bsc_mainnet: { 109 | provider: () => new HDWalletProvider(mnemonic, `https://bsc-dataseed.binance.org`), 110 | network_id: 56, // Ropsten's id 111 | gas: 3000000, // Ropsten has a lower block limit than mainnet 112 | confirmations: 2, // # of confs to wait between deployments. (default: 0) 113 | timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50) 114 | skipDryRun: true, // Skip dry run before migrations? (default: false for public nets ) 115 | gasPrice: 10000000000 116 | } 117 | // Useful for private networks 118 | // private: { 119 | // provider: () => new HDWalletProvider(mnemonic, `https://network.io`), 120 | // network_id: 2111, // This network is yours, in the cloud. 121 | // production: true // Treats this network as if it was a public net. (default: false) 122 | // } 123 | }, 124 | 125 | // Set default mocha options here, use special reporters etc. 126 | mocha: { 127 | // timeout: 100000 128 | }, 129 | 130 | // Configure your compilers 131 | compilers: { 132 | solc: { 133 | version: "0.8.9", // Fetch exact version from solc-bin (default: truffle's version) 134 | // docker: true, // Use "0.5.1" you've installed locally with docker (default: false) 135 | settings: { // See the solidity docs for advice about optimization and evmVersion 136 | optimizer: { 137 | enabled: true, 138 | runs: 200 139 | }, 140 | // evmVersion: "byzantium" 141 | } 142 | }, 143 | }, 144 | api_keys: {//https://ethereum.stackexchange.com/questions/19437/etherscan-how-can-i-verify-a-contract-with-multiple-imports-deployed-with-truff/20887 145 | etherscan: 'A7EAG5WB4FRAHIURRGWD8HSTM8CVYXZGZ4', //truffle run verify SwapContract LPToken --network ropsten 146 | bscscan: 'VDKSF7XEFIHS9JT8S5B5DH7H3MAIPGMBQ7' 147 | //https://www.npmjs.com/package/truffle-plugin-verify 148 | }, 149 | plugins: [ 150 | "@chainsafe/truffle-plugin-abigen", 151 | "truffle-contract-size", /*compile first, then run: truffle run contract-size*/ 152 | 'truffle-plugin-verify' 153 | ] 154 | 155 | }; 156 | -------------------------------------------------------------------------------- /web3_test/testLPToken.js: -------------------------------------------------------------------------------- 1 | const { BN, constants, expectEvent, expectRevert } = require('@openzeppelin/test-helpers'); 2 | const { expect } = require('chai'); 3 | const { ZERO_ADDRESS } = constants; 4 | 5 | const LPToken = artifacts.require('LPToken'); 6 | 7 | const TOKEN_DECIMALS = process.env.TOKEN_DECIMALS || 18 8 | 9 | contract('LPToken', function (accounts) { 10 | const [sender, receiver] = accounts 11 | const name = "Swingby BTC LP Token"; 12 | const symbol = 'sbBTC'; 13 | 14 | beforeEach(async function () { 15 | // The bundled BN library is the same one web3 uses under the hood 16 | this.value = new BN(1); 17 | 18 | this.token = await LPToken.new(TOKEN_DECIMALS) 19 | 20 | this.mintValue = new BN(500).mul(new BN(10).pow(new BN(TOKEN_DECIMALS))) 21 | 22 | await this.token.mint(sender, this.mintValue) 23 | }); 24 | 25 | it('has a name', async function () { 26 | expect(await this.token.name()).to.equal(name); 27 | }); 28 | 29 | it('has a symbol', async function () { 30 | expect(await this.token.symbol()).to.equal(symbol); 31 | }); 32 | 33 | it('has right decimals', async function () { 34 | decimals = await this.token.decimals() 35 | expect(decimals).to.bignumber.equal(new BN(TOKEN_DECIMALS)); 36 | }); 37 | 38 | it('reverts when minting tokens from not owner', async function () { 39 | // Conditions that trigger a require statement can be precisely tested 40 | await expectRevert( 41 | this.token.mint(receiver, this.value, { from: receiver }), 42 | 'Ownable: caller is not the owner', 43 | ); 44 | }); 45 | 46 | it('reverts when transferring tokens to the zero address', async function () { 47 | // Conditions that trigger a require statement can be precisely tested 48 | await expectRevert( 49 | this.token.transfer(constants.ZERO_ADDRESS, this.value, { from: sender }), 50 | 'ERC20: transfer to the zero address', 51 | ); 52 | }); 53 | 54 | it('emits a Transfer event on successful transfers', async function () { 55 | const receipt = await this.token.transfer( 56 | receiver, this.value, { from: sender } 57 | ); 58 | 59 | // Event assertions can verify that the arguments are the expected ones 60 | expectEvent(receipt, 'Transfer', { 61 | from: sender, 62 | to: receiver, 63 | value: this.value, 64 | }); 65 | }); 66 | 67 | it('updates balances on successful transfers', async function () { 68 | this.token.transfer(receiver, this.value, { from: sender }); 69 | 70 | // BN assertions are automatically available via chai-bn (if using Chai) 71 | balanceOfReceiver = await this.token.balanceOf(receiver) 72 | expect(balanceOfReceiver.sub(this.value)).to.bignumber.equal('0') 73 | }); 74 | 75 | it('emits a Burn event on successful burning', async function () { 76 | const burn = await this.token.burn( 77 | this.mintValue, { from: sender } 78 | ); 79 | 80 | // Event assertions can verify that the arguments are the expected ones 81 | expectEvent(burn, 'Transfer', { 82 | from: sender, 83 | to: ZERO_ADDRESS, 84 | value: this.mintValue, 85 | }); 86 | }); 87 | }) -------------------------------------------------------------------------------- /web3_test/testSwapContractFactory.js: -------------------------------------------------------------------------------- 1 | const { BN, constants, expectEvent, expectRevert } = require('@openzeppelin/test-helpers'); 2 | const { expect } = require('chai'); 3 | const { ZERO_ADDRESS } = constants; 4 | const WBTC_ADDR = "0xEb47a21C1fC00D1E863019906df1771b80DBE182" 5 | 6 | const LPToken = artifacts.require('LPToken'); 7 | const SwapContract = artifacts.require('SwapContract'); 8 | const SwapContractFactory = artifacts.require('SwapContractFactory'); 9 | 10 | const TOKEN_DECIMALS = process.env.TOKEN_DECIMALS || 18 11 | 12 | contract('SwapFactory', function (accounts) { 13 | const [sender, receiver] = accounts; 14 | 15 | beforeEach(async function () { 16 | // The bundled BN library is the same one web3 uses under the hood 17 | this.value = new BN(1); 18 | 19 | this.btctTest = await LPToken.new(TOKEN_DECIMALS) 20 | 21 | this.btctDecimals = await this.btctTest.decimals() 22 | 23 | this.mintValue = new BN(500).mul(new BN(10).pow(this.btctDecimals)) 24 | 25 | this.factory = await SwapContractFactory.new(); 26 | }); 27 | 28 | it('Deploy new contracts and checking the owner', async function () { 29 | const sc = await this.factory.deployNewContracts(receiver, this.btctTest.address, TOKEN_DECIMALS, 0) 30 | const newLPToken = await LPToken.at(sc.receipt.logs[0].args.lpToken) 31 | const newSwapContract = await SwapContract.at(sc.receipt.logs[0].args.swapContract) 32 | 33 | expect(await newLPToken.getOwner()).to.equal(newSwapContract.address) 34 | expect(await newSwapContract.owner()).to.equal(receiver) 35 | }) 36 | }) --------------------------------------------------------------------------------