diff --git a/.gitleaksignore b/.gitleaksignore index ecaf64d8..d8e0189d 100644 --- a/.gitleaksignore +++ b/.gitleaksignore @@ -135,4 +135,58 @@ f78d4539c80abb33ea04dce4d561af5302033235:scripts/deployment/staking/globals_sepo 9fa4b1fb81ba553ed48ef4a9b22c53ecdf4d2242:scripts/deployment/staking/globals_sepolia.json:generic-api-key:1 9fa4b1fb81ba553ed48ef4a9b22c53ecdf4d2242:scripts/deployment/staking/globals_sepolia.json:generic-api-key:2 001d71fc7c216c593faebdd3d6f353efaf80605f:scripts/deployment/staking/globals_sepolia.json:generic-api-key:1 -001d71fc7c216c593faebdd3d6f353efaf80605f:scripts/deployment/staking/globals_sepolia.json:generic-api-key:2 \ No newline at end of file +001d71fc7c216c593faebdd3d6f353efaf80605f:scripts/deployment/staking/globals_sepolia.json:generic-api-key:2 +ea6713128995ac18f3911c0214163e2b82896a7f:scripts/deployment/globals_mainnet.json:generic-api-key:1 +ea6713128995ac18f3911c0214163e2b82896a7f:scripts/deployment/globals_mainnet.json:generic-api-key:2 +1a7a855a853d2bc21e1e9178754a22dae54439f3:scripts/deployment/staking/globals_mainnet.json:generic-api-key:1 +1a7a855a853d2bc21e1e9178754a22dae54439f3:scripts/deployment/staking/globals_mainnet.json:generic-api-key:2 +3c5c0643bfa60605d7b91eb4b7a4b80c6f7a1b43:scripts/deployment/staking/globals_mainnet.json:generic-api-key:1 +3c5c0643bfa60605d7b91eb4b7a4b80c6f7a1b43:scripts/deployment/staking/globals_mainnet.json:generic-api-key:2 +b17bdd0ebae90b769b8756da81d831a70fcb4af3:scripts/deployment/globals_mainnet.json:generic-api-key:1 +b17bdd0ebae90b769b8756da81d831a70fcb4af3:scripts/deployment/staking/globals_mainnet.json:generic-api-key:1 +b17bdd0ebae90b769b8756da81d831a70fcb4af3:scripts/deployment/globals_mainnet.json:generic-api-key:2 +b17bdd0ebae90b769b8756da81d831a70fcb4af3:scripts/deployment/staking/globals_mainnet.json:generic-api-key:2 +c5ba11d1b46a6fa9644c0de28b4b0f7b154156ee:scripts/deployment/globals_mainnet.json:generic-api-key:1 +c5ba11d1b46a6fa9644c0de28b4b0f7b154156ee:scripts/deployment/globals_mainnet.json:generic-api-key:2 +c5ba11d1b46a6fa9644c0de28b4b0f7b154156ee:scripts/deployment/staking/globals_mainnet.json:generic-api-key:1 +c5ba11d1b46a6fa9644c0de28b4b0f7b154156ee:scripts/deployment/staking/globals_mainnet.json:generic-api-key:2 +7cf3cd1c5fa705f82f0f33c90538fa6e6892af5b:scripts/deployment/globals_mainnet.json:generic-api-key:1 +7cf3cd1c5fa705f82f0f33c90538fa6e6892af5b:scripts/deployment/staking/globals_mainnet.json:generic-api-key:1 +7cf3cd1c5fa705f82f0f33c90538fa6e6892af5b:scripts/deployment/globals_mainnet.json:generic-api-key:2 +7cf3cd1c5fa705f82f0f33c90538fa6e6892af5b:scripts/deployment/staking/globals_mainnet.json:generic-api-key:2 +38ff93e8e51ef86b6c46872b12e27f67152ec07a:scripts/deployment/staking/wormhole/test/globals_celo_mainnet.json:generic-api-key:1 +38ff93e8e51ef86b6c46872b12e27f67152ec07a:scripts/deployment/staking/wormhole/test/globals_celo_mainnet.json:generic-api-key:2 +38ff93e8e51ef86b6c46872b12e27f67152ec07a:scripts/deployment/staking/wormhole/globals_celo_mainnet.json:generic-api-key:1 +38ff93e8e51ef86b6c46872b12e27f67152ec07a:scripts/deployment/staking/wormhole/globals_celo_mainnet.json:generic-api-key:2 +cfe4b8064bfda91d83bd5bdc5af44f2155859ef3:scripts/deployment/staking/wormhole/test/globals_celo_mainnet.json:generic-api-key:1 +cfe4b8064bfda91d83bd5bdc5af44f2155859ef3:scripts/deployment/staking/wormhole/test/globals_celo_mainnet.json:generic-api-key:2 +cfe4b8064bfda91d83bd5bdc5af44f2155859ef3:scripts/deployment/staking/wormhole/globals_celo_mainnet.json:generic-api-key:1 +cfe4b8064bfda91d83bd5bdc5af44f2155859ef3:scripts/deployment/staking/wormhole/globals_celo_mainnet.json:generic-api-key:2 +e09cdb5c34a402545d5a67d65ea31760f7c0fd19:scripts/deployment/globals_mainnet.json:generic-api-key:1 +e09cdb5c34a402545d5a67d65ea31760f7c0fd19:scripts/deployment/globals_mainnet.json:generic-api-key:2 +02f626605f59ee89a44152d2d8723c848174e44:scripts/deployment/staking/globals_sepolia.json:generic-api-key:2 +f02f626605f59ee89a44152d2d8723c848174e44:scripts/deployment/globals_mainnet.json:generic-api-key:2 +a1fb94f332608c58c44aed99a08fea5fb08fc6ed:scripts/deployment/staking/globals_mainnet.json:generic-api-key:1 +b92c814bbbab19139c4d40d31f7d0394e2796d0f:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:1 +d3c5ea3ef6d62f5cfb51d2485b74133f84d40f7d:scripts/deployment/staking/globals_mainnet.json:generic-api-key:1 +d79d6210c89d103448e32b7c915903c8a8b8d87a:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:1 +d79d6210c89d103448e32b7c915903c8a8b8d87a:scripts/deployment/staking/globals_mainnet.json:generic-api-key:1 +e9945cd0dd6c8c0dc0fefda76d7f60e7ef56511b:scripts/deployment/globals_mainnet.json:generic-api-key:1 +e9945cd0dd6c8c0dc0fefda76d7f60e7ef56511b:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:1 +e9945cd0dd6c8c0dc0fefda76d7f60e7ef56511b:scripts/deployment/staking/globals_mainnet.json:generic-api-key:1 +e9945cd0dd6c8c0dc0fefda76d7f60e7ef56511b:scripts/deployment/staking/globals_sepolia.json:generic-api-key:1 +a1fb94f332608c58c44aed99a08fea5fb08fc6ed:scripts/deployment/staking/globals_mainnet.json:generic-api-key:2 +b92c814bbbab19139c4d40d31f7d0394e2796d0f:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:2 +d3c5ea3ef6d62f5cfb51d2485b74133f84d40f7d:scripts/deployment/staking/globals_mainnet.json:generic-api-key:2 +d79d6210c89d103448e32b7c915903c8a8b8d87a:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:2 +d79d6210c89d103448e32b7c915903c8a8b8d87a:scripts/deployment/staking/globals_mainnet.json:generic-api-key:2 +e9945cd0dd6c8c0dc0fefda76d7f60e7ef56511b:scripts/deployment/globals_mainnet.json:generic-api-key:2 +e9945cd0dd6c8c0dc0fefda76d7f60e7ef56511b:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:2 +e9945cd0dd6c8c0dc0fefda76d7f60e7ef56511b:scripts/deployment/staking/globals_mainnet.json:generic-api-key:2 +e9945cd0dd6c8c0dc0fefda76d7f60e7ef56511b:scripts/deployment/staking/globals_sepolia.json:generic-api-key:2 +3068b0eefad400612f18c193fa62e11974c0fbd5:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:1 +3068b0eefad400612f18c193fa62e11974c0fbd5:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:2 +b616524545db2768fb9a3772ffd05c6e0a7f2d8b:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:1 +b616524545db2768fb9a3772ffd05c6e0a7f2d8b:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:2 +5e43d545806f8e2d6e8ffd8190d7d704bf663d5f:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:1 +5e43d545806f8e2d6e8ffd8190d7d704bf663d5f:scripts/deployment/staking/celo/globals_celo_mainnet.json:generic-api-key:2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 259faf48..2913eb37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,21 @@ All notable changes to this project will be documented in this file. The format is based on [Common Changelog](https://common-changelog.org). +[1.2.2]: https://github.com/valory-xyz/autonolas-tokenomics/compare/v1.0.3...v1.2.2 [1.0.3]: https://github.com/valory-xyz/autonolas-tokenomics/compare/v1.0.2...v1.0.3 [1.0.2]: https://github.com/valory-xyz/autonolas-tokenomics/compare/v1.0.1...v1.0.2 [1.0.1]: https://github.com/valory-xyz/autonolas-tokenomics/compare/v1.0.0...v1.0.1 [1.0.0]: https://github.com/valory-xyz/autonolas-tokenomics/releases/tag/v1.0.0 +## [1.2.2] - 2024-07-29 + +### Changed + +- Introducing Service Staking according to [PoAA Whitepaper](https://staking.olas.network/poaa-whitepaper.pdf) +- Refactored and re-deployed `Tokenomics.sol` and `Dispenser.sol` to address service staking inflation and claiming capability ([#156](https://github.com/valory-xyz/autonolas-registries/pull/156)), with the subsequent internal audit ([#168](https://github.com/valory-xyz/autonolas-registries/pull/168)) +- Created and deployed `ArbitrumDepositProcessorL1.sol`, `ArbitrumTargetDispenserL2.sol`, `DefaultDepositProcessorL1.sol`, `DefaultTargetDispenserL2.sol`, `EthereumDepositProcessor.sol`, `GnosisDepositProcessorL1.sol` , `GnosisTargetDispenserL2.sol`, `OptimismDepositProcessorL1.sol`, `OptimismTargetDispenserL2.sol`, `PolygonDepositProcessorL1.sol`, `PolygonTargetDispenserL2.sol`, `WormholeDepositProcessorL1.sol`, and `WormholeTargetDispenserL2.sol` contracts +- Participated in a complete [C4R audit competition](https://github.com/code-423n4/2024-05-olas-findings) and addressed findings + ## [1.0.3] - 2023-10-05 _No bytecode changes_. diff --git a/abis/0.8.25/Dispenser.json b/abis/0.8.25/Dispenser.json index 7088a562..475842a3 100644 --- a/abis/0.8.25/Dispenser.json +++ b/abis/0.8.25/Dispenser.json @@ -213,6 +213,19 @@ "name": "ZeroValue", "type": "error" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "nomineeHash", + "type": "bytes32" + } + ], + "name": "AddNomineeHash", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -233,6 +246,18 @@ "internalType": "uint256", "name": "topUp", "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "unitTypes", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "unitIds", + "type": "uint256[]" } ], "name": "IncentivesClaimed", @@ -264,6 +289,19 @@ "name": "PauseDispenser", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "nomineeHash", + "type": "bytes32" + } + ], + "name": "RemoveNomineeHash", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -311,6 +349,67 @@ "name": "account", "type": "address" }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "chainIds", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "bytes32[][]", + "name": "stakingTargets", + "type": "bytes32[][]" + }, + { + "indexed": false, + "internalType": "uint256[][]", + "name": "stakingIncentives", + "type": "uint256[][]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalStakingIncentive", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalTransferAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalReturnAmount", + "type": "uint256" + } + ], + "name": "StakingIncentivesBatchClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "stakingTarget", + "type": "bytes32" + }, { "indexed": false, "internalType": "uint256", @@ -990,8 +1089,8 @@ "type": "function" } ], - "bytecode": "0x610120604052348015610010575f80fd5b50604051614b01380380614b0183398101604081905261002f91610226565b6002805460ff60a01b1933166001600160a81b031990911617600160a01b1760ff60a81b1916600160a91b1790556001600160a01b038916158061007a57506001600160a01b038816155b8061008c57506001600160a01b038716155b8061009e57506001600160a01b038616155b806100a7575084155b156100c55760405163d92e233d60e01b815260040160405180910390fd5b8315806100d0575082155b806100d9575081155b806100e2575080155b1561010057604051637c946ed760e01b815260040160405180910390fd5b61ffff82111561013357604051637ae5968560e01b81526004810183905261ffff60248201526044015b60405180910390fd5b6001600160601b0381111561016b57604051637ae5968560e01b8152600481018290526001600160601b03602482015260440161012a565b6001600160a01b0398891660c05260038054988a166001600160a01b0319998a1617905560048054978a16978916979097179096556005805495909816949096169390931790955560e0819052604080518082018252828152466020918201908152825180830194909452518383015281518084038301815260609093019091528151910120610100525f9390935560019290925560805260a0526102a5565b80516001600160a01b0381168114610221575f80fd5b919050565b5f805f805f805f805f6101208a8c03121561023f575f80fd5b6102488a61020b565b985061025660208b0161020b565b975061026460408b0161020b565b965061027260608b0161020b565b955060808a0151945060a08a0151935060c08a0151925060e08a015191506101008a015190509295985092959850929598565b60805160a05160c05160e0516101005161479361036e5f395f81816103450152818161141401528181611cf50152611d9c01525f8181610671015281816114470152818161169b015281816116cf01528181611d2c01528181611ec60152818161318e01526131f401525f81816101ef015281816109c201528181610ac901528181610e4901528181610f98015281816126a3015281816127b001528181612ae4015261354c01525f818161063e01526118a401525f818161029c015261187001526147935ff3fe6080604052600436106101da575f3560e01c806379bc81dd116100fd578063bc7d5c5c11610092578063dcb5ccc411610062578063dcb5ccc4146105f9578063e09177781461062d578063e6be59e714610660578063f4da12ba14610693575f80fd5b8063bc7d5c5c14610568578063d529779314610587578063d7accbcc146105a6578063d8bf69bf146105da575f80fd5b80639649a35c116100cd5780639649a35c146104eb578063a5edd4fc146104ff578063a6f9dae11461051e578063bb78678f1461053d575f80fd5b806379bc81dd1461046e5780638513e77d1461048d5780638833c205146104b85780638da5cb5b146104cc575f80fd5b80633c18d1dd1161017357806361d027b31161014357806361d027b3146103d257806363096509146103f157806363c4d28e14610410578063777e49c91461042f575f80fd5b80633c18d1dd146103345780634ac7251d146103675780635a55a482146103865780635c975abb146103a5575f80fd5b80632ad923dc116101ae5780632ad923dc146102cc5780632c0f3f29146102f757806334be5af41461030c5780633907196c14610321575f80fd5b806231d115146101de5780630d17db111461022e5780630d3241ee1461026c5780632a3bb6931461028b575b5f80fd5b3480156101e9575f80fd5b506102117f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b348015610239575f80fd5b5061025c610248366004613c36565b600a6020525f908152604090205460ff1681565b6040519015158152602001610225565b348015610277575f80fd5b50600554610211906001600160a01b031681565b348015610296575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610225565b3480156102d7575f80fd5b506102be6102e6366004613c36565b60066020525f908152604090205481565b61030a610305366004613cfe565b6106a7565b005b348015610317575f80fd5b506102be60015481565b61030a61032f366004613e5e565b610be6565b34801561033f575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b348015610372575f80fd5b50600354610211906001600160a01b031681565b348015610391575f80fd5b5061030a6103a0366004613fde565b611148565b3480156103b0575f80fd5b506002546103c590600160a81b900460ff1681565b604051610225919061401b565b3480156103dd575f80fd5b50600454610211906001600160a01b031681565b3480156103fc575f80fd5b5061030a61040b366004614041565b611312565b34801561041b575f80fd5b5061030a61042a366004613c36565b6113d1565b34801561043a575f80fd5b5061044e610449366004614066565b611654565b604080519485526020850193909352918301526060820152608001610225565b348015610479575f80fd5b5061030a610488366004613fde565b611b99565b348015610498575f80fd5b506102be6104a7366004613c36565b60076020525f908152604090205481565b3480156104c3575f80fd5b506102be5f5481565b3480156104d7575f80fd5b50600254610211906001600160a01b031681565b3480156104f6575f80fd5b5061030a611ca8565b34801561050a575f80fd5b5061030a610519366004613c36565b61204a565b348015610529575f80fd5b5061030a6105383660046140b0565b6121ed565b348015610548575f80fd5b506102be610557366004613c36565b60096020525f908152604090205481565b348015610573575f80fd5b5061030a6105823660046140c9565b6122aa565b348015610592575f80fd5b5061030a6105a13660046140e9565b61235a565b3480156105b1575f80fd5b506105c56105c0366004614129565b6124c8565b60408051928352602083019190915201610225565b3480156105e5575f80fd5b5061030a6105f4366004614189565b6128f9565b348015610604575f80fd5b50610211610613366004613c36565b60086020525f90815260409020546001600160a01b031681565b348015610638575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b34801561066b575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b34801561069e575f80fd5b506102be612a5c565b6002546001600160a01b90910460ff1611156106d6576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b1790555f83900361070a57604051637c946ed760e01b815260040160405180910390fd5b5f82900361072b5760405163d92e233d60e01b815260040160405180910390fd5b5f548085111561075d57604051637ae5968560e01b815260048101869052602481018290526044015b60405180910390fd5b60028054600160a81b900460ff169081600381111561077e5761077e614007565b148061079b5750600381600381111561079957610799614007565b145b8061081257506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af11580156107e7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061080b919061423c565b60ff166002145b15610830576040516313d0ff5960e31b815260040160405180910390fd5b5f8581526008602090815260408083205481517fa8b2ae0200000000000000000000000000000000000000000000000000000000815291516001600160a01b039091169392849263a8b2ae0292600480830193928290030181865afa15801561089b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108bf9190614255565b90505f805f806108d18c8c8c88611654565b5f81815260066020526040902082905592965090945092509050821561094b57600354604051635e148f0960e11b8152600481018590526001600160a01b039091169063bc291e12906024015f604051808303815f87803b158015610934575f80fd5b505af1158015610946573d5f803e3d5ffd5b505050505b5f8415610b8157505f8b815260096020526040902054849080156109a5578181106109845761097a8282614280565b90505f9150610994565b61098e8183614280565b91505f90505b5f8d81526009602052604090208190555b8115610b72576040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610a0f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a339190614255565b60048054604051637ff796ab60e01b815230928101929092525f6024830152604482018690529192506001600160a01b0390911690637ff796ab906064016020604051808303815f875af1158015610a8d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ab19190614299565b506040516370a0823160e01b815230600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610b16573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3a9190614255565b610b449190614280565b9050828114610b705760405163312b003360e01b81526004810182905260248101849052604401610754565b505b610b7f8d8d888e86612a88565b505b604080518681526020810183905290810185905233907f02b21954a7bf2d6a171db9a87b430a3723605c554db00adcb95b26ce8464f2809060600160405180910390a250506002805460ff60a01b1916600160a01b1790555050505050505050505050565b6002546001600160a01b90910460ff161115610c15576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b179055610c3484848484612c86565b5f5480861115610c6157604051637ae5968560e01b81526004810187905260248101829052604401610754565b60028054600160a81b900460ff1690816003811115610c8257610c82614007565b1480610c9f57506003816003811115610c9d57610c9d614007565b145b80610d1657506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af1158015610ceb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d0f919061423c565b60ff166002145b15610d34576040516313d0ff5960e31b815260040160405180910390fd5b6060806060610d448a8a8a612f84565b825192955090935091505f9084906002908110610d6357610d636142b8565b60200260200101511115610def5760035483516001600160a01b039091169063bc291e129085906002908110610d9b57610d9b6142b8565b60200260200101516040518263ffffffff1660e01b8152600401610dc191815260200190565b5f604051808303815f87803b158015610dd8575f80fd5b505af1158015610dea573d5f803e3d5ffd5b505050505b5f835f81518110610e0257610e026142b8565b60200260200101511115611086575f83600181518110610e2457610e246142b8565b60200260200101511115611078576040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610e96573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610eba9190614255565b60045485519192506001600160a01b031690637ff796ab9030905f9088906001908110610ee957610ee96142b8565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b039093166004840152602483019190915260448201526064016020604051808303815f875af1158015610f5c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f809190614299565b506040516370a0823160e01b815230600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610fe5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110099190614255565b6110139190614280565b905083600181518110611028576110286142b8565b6020026020010151811461107657808460018151811061104a5761104a6142b8565b602002602001015160405163312b003360e01b8152600401610754929190918252602082015260400190565b505b6110868989848a858b6134de565b336001600160a01b03167f02b21954a7bf2d6a171db9a87b430a3723605c554db00adcb95b26ce8464f280845f815181106110c3576110c36142b8565b6020026020010151856001815181106110de576110de6142b8565b6020026020010151866002815181106110f9576110f96142b8565b6020026020010151604051611121939291909283526020830191909152604082015260600190565b60405180910390a250506002805460ff60a01b1916600160a01b1790555050505050505050565b6002546001600160a01b031633146111885760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b821580611193575081155b8061119c575080155b156111ba57604051637c946ed760e01b815260040160405180910390fd5b4683036111dd57604051633881b68960e01b815260048101849052602401610754565b5f838152600960205260408120546111f69084906142cc565b90506bffffffffffffffffffffffff81111561123a57604051637ae5968560e01b8152600481018290526bffffffffffffffffffffffff6024820152604401610754565b5f8481526009602090815260408083208490556008909152908190205490517fac65ded2000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b0390911690819063ac65ded2906024015f604051808303815f87803b1580156112b1575f80fd5b505af11580156112c3573d5f803e3d5ffd5b505060408051888152602081018890529081018590528592507f2192822efd68ddf583804c65675b73a59694e672cab1758eb6714613f932a97591506060015b60405180910390a25050505050565b6002546001600160a01b031633146113525760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b600280548291907fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff16600160a81b83600381111561139257611392614007565b02179055507fa814f27828c0243d429ea8c7033cb10f0c825b9466fdc04f63e0cca26c28eb8a816040516113c6919061401b565b60405180910390a150565b6005546001600160a01b031633146114115760055460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610754565b807f00000000000000000000000000000000000000000000000000000000000000000361147357604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b600354604080517f14b19c5a00000000000000000000000000000000000000000000000000000000815290515f926001600160a01b0316916314b19c5a9160048083019260209291908290030181865afa1580156114d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114f791906142df565b60035463ffffffff9190911691505f906001600160a01b031663d4ee9f8d611520600185614280565b6040518263ffffffff1660e01b815260040161153e91815260200190565b602060405180830381865afa158015611559573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061157d9190614255565b90505f60035f9054906101000a90046001600160a01b03166001600160a01b031663d2b3996f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115d0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115f491906142df565b63ffffffff1690505f62093a8061160b83856142cc565b6116159190614280565b905080421061164057604051637ae5968560e01b815242600482015260248101829052604401610754565b5050505f9182526007602052604090912055565b5f805f80865f0361167857604051637c946ed760e01b815260040160405180910390fd5b5f8690036116995760405163d92e233d60e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000086036116fb57604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b5060408051808201825286815260209081018881528251808301899052905181840152825180820384018152606090910190925281519101205f61173f828a613ae7565b6005546040516317d5e89d60e31b8152600481018b9052602481018c90529195509192506001600160a01b039091169063beaf44e8906044015f604051808303815f87803b15801561178f575f80fd5b505af11580156117a1573d5f803e3d5ffd5b5083925050505b83811015611b8c575f818152600a602052604090205460ff16611b8457600354604051631ddf133560e01b8152600481018390525f916001600160a01b031690631ddf133590602401608060405180830381865afa15801561180c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611830919061431d565b606081015190915060ff16156118cf57604081015161ffff16158015611866575060208101516bffffffffffffffffffffffff16155b156118ca5761ffff7f00000000000000000000000000000000000000000000000000000000000000001660408201526bffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660208201525b6118d5565b50611b84565b60035460405163d4ee9f8d60e01b8152600481018490525f916001600160a01b03169063d4ee9f8d90602401602060405180830381865afa15801561191c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119409190614255565b600554604051630c88d47f60e41b8152600481018d9052602481018e9052604481018390529192505f9182916001600160a01b03169063c88d47f0906064016040805180830381865afa158015611999573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119bd91906143a0565b91509150805f03611a05575f858152600a60205260409020805460ff1916600117905583516119fa906bffffffffffffffffffffffff168a6142cc565b985050505050611b84565b83515f9081906bffffffffffffffffffffffff168184821115611a3257611a2c8583614280565b90508491505b6040880151611a4b9061ffff16655af3107a40006143c2565b861015611a8157670de0b6b3a764000086611a6684846142cc565b611a7091906143c2565b611a7a91906143ed565b9250611b6f565b670de0b6b3a7640000611a9487846143c2565b611a9e91906143ed565b9350670de0b6b3a7640000611ab387836143c2565b611abd91906143ed565b925087602001516bffffffffffffffffffffffff16915081841115611af657611ae68285614280565b611af090846142cc565b92508193505b60128f1015611b62575f8f6012611b0d9190614280565b611b1890600a6144e0565b611b2290866143ed565b90508f6012611b319190614280565b611b3c90600a6144e0565b611b4690826143c2565b9050611b528186614280565b611b5c90856142cc565b90945092505b611b6c848f6142cc565b9d505b611b79838e6142cc565b9c5050505050505050505b6001016117a8565b5050945094509450949050565b5f838152600860205260409020546001600160a01b0316338114611bfa576040517fdeeeedec0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0382166024820152604401610754565b5f84815260096020526040812054611c139085906142cc565b90506bffffffffffffffffffffffff811115611c5757604051637ae5968560e01b8152600481018290526bffffffffffffffffffffffff6024820152604401610754565b5f85815260096020908152604091829020839055815187815290810186905290810182905283907f2192822efd68ddf583804c65675b73a59694e672cab1758eb6714613f932a97590606001611303565b6002546001600160a01b90910460ff161115611cd7576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b1790555f80548190611d1a907f000000000000000000000000000000000000000000000000000000000000000090613ae7565b6005546040516317d5e89d60e31b81527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201529294509092506001600160a01b03169063beaf44e8906044015f604051808303815f87803b158015611d86575f80fd5b505af1158015611d98573d5f803e3d5ffd5b50507f00000000000000000000000000000000000000000000000000000000000000005f90815260066020526040812084905591508390505b82811015611f8857600354604051631ddf133560e01b8152600481018390525f916001600160a01b031690631ddf133590602401608060405180830381865afa158015611e20573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e44919061431d565b60035460405163d4ee9f8d60e01b8152600481018590529192505f916001600160a01b039091169063d4ee9f8d90602401602060405180830381865afa158015611e90573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611eb49190614255565b600554604051630c88d47f60e41b81527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604481018390529192505f916001600160a01b039091169063c88d47f0906064016040805180830381865afa158015611f2b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f4f91906143a0565b508351909150611f6e9082906bffffffffffffffffffffffff166143c2565b611f7890866142cc565b9450505050806001019050611dd1565b50611f9b670de0b6b3a7640000826143ed565b90508015611ffd57600354604051635e148f0960e11b8152600481018390526001600160a01b039091169063bc291e12906024015f604051808303815f87803b158015611fe6575f80fd5b505af1158015611ff8573d5f803e3d5ffd5b505050505b60405181815233907f2a8de497d698d6869cb0844411788378e76214d03a541eec6ba514b795d9f42e9060200160405180910390a250506002805460ff60a01b1916600160a01b17905550565b6005546001600160a01b0316331461208a5760055460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610754565b60028054600160a81b900460ff16908160038111156120ab576120ab614007565b14806120c8575060038160038111156120c6576120c6614007565b145b8061213f57506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af1158015612114573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612138919061423c565b60ff166002145b1561215d576040516313d0ff5960e31b815260040160405180910390fd5b60035f9054906101000a90046001600160a01b03166001600160a01b03166314b19c5a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121ad573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121d191906142df565b5f9283526006602052604090922063ffffffff90921690915550565b6002546001600160a01b0316331461222d5760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b6001600160a01b0381166122545760405163d92e233d60e01b815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f4ffd725fc4a22075e9ec71c59edf9c38cdeb588a91b24fc5b61388c5be41282b905f90a250565b6002546001600160a01b031633146122ea5760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b8115806122f5575080155b1561231357604051637c946ed760e01b815260040160405180910390fd5b5f829055600181905560408051838152602081018390527f61f6c4cc9665a257352c0b46189ffc2ae6fbbc11e155ff20901217ff203a517e91015b60405180910390a15050565b6002546001600160a01b0316331461239a5760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b6001600160a01b038316156123fd576003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0385169081179091556040517f4672fe7e13cfb163442d0b729b5733fb3efafc66cbe3677eac9940eb41c284c2905f90a25b6001600160a01b03821615612460576004805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384169081179091556040517f7dae230f18360d76a040c81f050aa14eb9d6dc7901b20fc5d855e2a20fe814d1905f90a25b6001600160a01b038116156124c3576005805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f04a606379838ed6fc83fd189eea9d1835b5eff05035c4b74622911ea2ae6b217905f90a25b505050565b5f806001600260149054906101000a900460ff1660ff1611156124fe576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b179081905560ff600160a81b90910416600181600381111561253257612532614007565b148061254f5750600381600381111561254d5761254d614007565b145b806125c657506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af115801561259b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125bf919061423c565b60ff166002145b156125e4576040516313d0ff5960e31b815260040160405180910390fd5b6003546040517f2e070f540000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690632e070f549061263190339089908990600401614525565b60408051808303815f875af115801561264c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061267091906143a0565b90935091505f8061268184866142cc565b1115612859575f8315612717576040516370a0823160e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156126f0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127149190614255565b90505b60048054604051637ff796ab60e01b8152339281019290925260248201879052604482018690526001600160a01b031690637ff796ab906064016020604051808303815f875af115801561276d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127919190614299565b91508315612857576040516370a0823160e01b815233600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156127fd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128219190614255565b61282b9190614280565b90508381146128575760405163312b003360e01b81526004810182905260248101859052604401610754565b505b806128a0576040517f942dc9da0000000000000000000000000000000000000000000000000000000081523360048201526024810185905260448101849052606401610754565b604080518581526020810185905233917f928890dff971de1394b7440848938a868d83445d2f7fb4b07938ae626c7cb130910160405180910390a250506002805460ff60a01b1916600160a01b17905590939092509050565b6002546001600160a01b031633146129395760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b8151158061294957508051825114155b1561297457815181516040516308151c1160e41b815260048101929092526024820152604401610754565b5f5b8151811015612a2a57818181518110612991576129916142b8565b60200260200101515f036129b857604051637c946ed760e01b815260040160405180910390fd5b8281815181106129ca576129ca6142b8565b602002602001015160085f8484815181106129e7576129e76142b8565b602002602001015181526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550806001019050612976565b507fe87460f6c400fa0166984512586d7bdf03a3230bbadf9651f27f08716dd77fa5828260405161234e92919061459a565b6024612a71600267ffffffffffffffff6145c7565b612a7b91906145ed565b67ffffffffffffffff1681565b5f858152600860205260409020546001600160a01b03168115612b50576040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b038281166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303815f875af1158015612b2a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b4e9190614299565b505b6024612b65600267ffffffffffffffff6145c7565b612b6f91906145ed565b67ffffffffffffffff168611612c02576040517fb2267a7b00000000000000000000000000000000000000000000000000000000815285906001600160a01b0383169063b2267a7b903490612bce9085908a908a908a90600401614643565b5f604051808303818588803b158015612be5575f80fd5b505af1158015612bf7573d5f803e3d5ffd5b505050505050612c7e565b6040517f6585ecdc0000000000000000000000000000000000000000000000000000000081526001600160a01b03821690636585ecdc903490612c4f90899089908990899060040161467b565b5f604051808303818588803b158015612c66575f80fd5b505af1158015612c78573d5f803e3d5ffd5b50505050505b505050505050565b8251845114612cb557835183516040516308151c1160e41b815260048101929092526024820152604401610754565b8151845114612ce457835182516040516308151c1160e41b815260048101929092526024820152604401610754565b8051845114612d1357835181516040516308151c1160e41b815260048101929092526024820152604401610754565b5f805f5b8651811015612f5a57868181518110612d3257612d326142b8565b60200260200101518310612d7657868181518110612d5257612d526142b8565b6020026020010151604051633881b68960e01b815260040161075491815260200190565b868181518110612d8857612d886142b8565b60200260200101519250858181518110612da457612da46142b8565b6020026020010151515f03612dcc57604051637c946ed760e01b815260040160405180910390fd5b838181518110612dde57612dde6142b8565b602002602001015182612df191906142cc565b91505f600154905080878381518110612e0c57612e0c6142b8565b6020026020010151511115612e5b57868281518110612e2d57612e2d6142b8565b60200260200101515181604051637ae5968560e01b8152600401610754929190918252602082015260400190565b5f805b888481518110612e7057612e706142b8565b602002602001015151811015612f4c57888481518110612e9257612e926142b8565b60200260200101518181518110612eab57612eab6142b8565b60200260200101515f1c825f1c10612f0c57888481518110612ecf57612ecf6142b8565b60200260200101518181518110612ee857612ee86142b8565b6020026020010151604051636aba776560e11b815260040161075491815260200190565b888481518110612f1e57612f1e6142b8565b60200260200101518181518110612f3757612f376142b8565b60200260200101519150806001019050612e5e565b505050806001019050612d17565b50803414612c7e5760405163312b003360e01b815234600482015260248101829052604401610754565b6040805160038082526080820190925260609182918291602082018380368337019050509250845167ffffffffffffffff811115612fc457612fc4613c4d565b604051908082528060200260200182016040528015612ff757816020015b6060815260200190600190039081612fe25790505b509150845167ffffffffffffffff81111561301457613014613c4d565b60405190808252806020026020018201604052801561303d578160200160208202803683370190505b5090505f5b85518110156134d4575f60085f888481518110613061576130616142b8565b602002602001015181526020019081526020015f205f9054906101000a90046001600160a01b031690505f816001600160a01b031663a8b2ae026040518163ffffffff1660e01b8152600401602060405180830381865afa1580156130c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130ec9190614255565b9050868381518110613100576131006142b8565b60200260200101515167ffffffffffffffff81111561312157613121613c4d565b60405190808252806020026020018201604052801561314a578160200160208202803683370190505b5085848151811061315d5761315d6142b8565b60200260200101819052505f5b87848151811061317c5761317c6142b8565b602002602001015151811015613363577f00000000000000000000000000000000000000000000000000000000000000008885815181106131bf576131bf6142b8565b602002602001015182815181106131d8576131d86142b8565b60200260200101510361322057604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b5f805f8061327b8e8e8a8151811061323a5761323a6142b8565b60200260200101518e8b81518110613254576132546142b8565b6020026020010151888151811061326d5761326d6142b8565b602002602001015189611654565b5f8181526006602052604090208290558d519397509195509350915084908b908a9081106132ab576132ab6142b8565b602002602001015186815181106132c4576132c46142b8565b602002602001018181525050838989815181106132e3576132e36142b8565b602002602001018181516132f791906142cc565b9052508a5184908c905f9061330e5761330e6142b8565b6020026020010181815161332291906142cc565b9052508a5183908c90600290811061333c5761333c6142b8565b6020026020010181815161335091906142cc565b905250506001909301925061316a915050565b505f848481518110613377576133776142b8565b60200260200101511115613486575f60095f8a868151811061339b5761339b6142b8565b602002602001015181526020019081526020015f205490505f811115613484578484815181106133cd576133cd6142b8565b60200260200101518110613426578484815181106133ed576133ed6142b8565b6020026020010151816134009190614280565b90505f858581518110613415576134156142b8565b602002602001018181525050613454565b80858581518110613439576134396142b8565b6020026020010181815161344d9190614280565b9052505f90505b8060095f8b878151811061346a5761346a6142b8565b602002602001015181526020019081526020015f20819055505b505b838381518110613498576134986142b8565b6020026020010151866001815181106134b3576134b36142b8565b602002602001018181516134c791906142cc565b9052505050600101613042565b5093509350939050565b5f5b8651811015613ade575f60085f8984815181106134ff576134ff6142b8565b602002602001015181526020019081526020015f205f9054906101000a90046001600160a01b031690505f84838151811061353c5761353c6142b8565b60200260200101511115613607577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb8286858151811061358c5761358c6142b8565b60200260200101516040518363ffffffff1660e01b81526004016135c59291906001600160a01b03929092168252602082015260400190565b6020604051808303815f875af11580156135e1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136059190614299565b505b5f8088848151811061361b5761361b6142b8565b60200260200101515167ffffffffffffffff81111561363c5761363c613c4d565b604051908082528060200260200182016040528015613665578160200160208202803683370190505b5090505f5b89858151811061367c5761367c6142b8565b6020026020010151518110156136fe575f89868151811061369f5761369f6142b8565b602002602001015182815181106136b8576136b86142b8565b602002602001015111156136f65760018282815181106136da576136da6142b8565b911515602092830291909101909101526136f383614699565b92505b60010161366a565b505f8267ffffffffffffffff81111561371957613719613c4d565b604051908082528060200260200182016040528015613742578160200160208202803683370190505b5090505f8367ffffffffffffffff81111561375f5761375f613c4d565b604051908082528060200260200182016040528015613788578160200160208202803683370190505b5090505f805b8c88815181106137a0576137a06142b8565b602002602001015151811015613884578481815181106137c2576137c26142b8565b60200260200101511561387c578c88815181106137e1576137e16142b8565b602002602001015181815181106137fa576137fa6142b8565b6020026020010151848381518110613814576138146142b8565b6020026020010181815250508b8881518110613832576138326142b8565b6020026020010151818151811061384b5761384b6142b8565b6020026020010151838381518110613865576138656142b8565b602090810291909101015261387982614699565b91505b60010161378e565b50602461389a600267ffffffffffffffff6145c7565b6138a491906145ed565b67ffffffffffffffff168d88815181106138c0576138c06142b8565b602002602001015111613a20575f835167ffffffffffffffff8111156138e8576138e8613c4d565b604051908082528060200260200182016040528015613911578160200160208202803683370190505b5090505f5b845181101561396d57848181518110613931576139316142b8565b60200260200101515f1c82828151811061394d5761394d6142b8565b6001600160a01b0390921660209283029190910190910152600101613916565b50866001600160a01b031663bde526618a8a8151811061398f5761398f6142b8565b602002602001015183868f8d815181106139ab576139ab6142b8565b60200260200101518f8e815181106139c5576139c56142b8565b60200260200101516040518663ffffffff1660e01b81526004016139ec94939291906146b1565b5f604051808303818588803b158015613a03575f80fd5b505af1158015613a15573d5f803e3d5ffd5b505050505050613acd565b856001600160a01b03166355442b59898981518110613a4157613a416142b8565b602002602001015185858e8c81518110613a5d57613a5d6142b8565b60200260200101518e8d81518110613a7757613a776142b8565b60200260200101516040518663ffffffff1660e01b8152600401613a9e94939291906146fb565b5f604051808303818588803b158015613ab5575f80fd5b505af1158015613ac7573d5f803e3d5ffd5b50505050505b5050505050508060010190506134e0565b50505050505050565b5f805f60035f9054906101000a90046001600160a01b03166001600160a01b03166314b19c5a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613b3a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613b5e91906142df565b5f86815260066020526040812054945063ffffffff919091169150839003613b9957604051637c946ed760e01b815260040160405180910390fd5b808303613bce5782613bac600183614280565b604051637ae5968560e01b815260048101929092526024820152604401610754565b5f85815260076020526040902054600181118015613bec5750808410155b15613bfd5783613bac600183614280565b613c0785856142cc565b9250600181118015613c1857508083115b15613c21578092505b81831115613c2d578192505b50509250929050565b5f60208284031215613c46575f80fd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613c8a57613c8a613c4d565b604052919050565b5f82601f830112613ca1575f80fd5b813567ffffffffffffffff811115613cbb57613cbb613c4d565b613cce601f8201601f1916602001613c61565b818152846020838601011115613ce2575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f8060808587031215613d11575f80fd5b843593506020850135925060408501359150606085013567ffffffffffffffff811115613d3c575f80fd5b613d4887828801613c92565b91505092959194509250565b5f67ffffffffffffffff821115613d6d57613d6d613c4d565b5060051b60200190565b5f82601f830112613d86575f80fd5b81356020613d9b613d9683613d54565b613c61565b8083825260208201915060208460051b870101935086841115613dbc575f80fd5b602086015b84811015613dd85780358352918301918301613dc1565b509695505050505050565b5f82601f830112613df2575f80fd5b81356020613e02613d9683613d54565b82815260059290921b84018101918181019086841115613e20575f80fd5b8286015b84811015613dd857803567ffffffffffffffff811115613e42575f80fd5b613e508986838b0101613c92565b845250918301918301613e24565b5f805f805f60a08688031215613e72575f80fd5b8535945067ffffffffffffffff8060208801351115613e8f575f80fd5b613e9f8860208901358901613d77565b94508060408801351115613eb1575f80fd5b6040870135870188601f820112613ec6575f80fd5b613ed3613d968235613d54565b81358082526020808301929160051b8401018b1015613ef0575f80fd5b602083015b6020843560051b850101811015613f8a578481351115613f13575f80fd5b803584018c603f820112613f25575f80fd5b613f35613d966020830135613d54565b602082810135808352908201919060051b83016040018f811115613f57575f80fd5b6040840193505b80841015613f79578335835260209384019390920191613f5e565b508552505060209283019201613ef5565b50955050506060870135811015613f9f575f80fd5b613faf8860608901358901613de3565b92508060808801351115613fc1575f80fd5b50613fd28760808801358801613d77565b90509295509295909350565b5f805f60608486031215613ff0575f80fd5b505081359360208301359350604090920135919050565b634e487b7160e01b5f52602160045260245ffd5b602081016004831061403b57634e487b7160e01b5f52602160045260245ffd5b91905290565b5f60208284031215614051575f80fd5b81356004811061405f575f80fd5b9392505050565b5f805f8060808587031215614079575f80fd5b5050823594602084013594506040840135936060013592509050565b80356001600160a01b03811681146140ab575f80fd5b919050565b5f602082840312156140c0575f80fd5b61405f82614095565b5f80604083850312156140da575f80fd5b50508035926020909101359150565b5f805f606084860312156140fb575f80fd5b61410484614095565b925061411260208501614095565b915061412060408501614095565b90509250925092565b5f806040838503121561413a575f80fd5b823567ffffffffffffffff80821115614151575f80fd5b61415d86838701613d77565b93506020850135915080821115614172575f80fd5b5061417f85828601613d77565b9150509250929050565b5f806040838503121561419a575f80fd5b823567ffffffffffffffff808211156141b1575f80fd5b818501915085601f8301126141c4575f80fd5b813560206141d4613d9683613d54565b82815260059290921b840181019181810190898411156141f2575f80fd5b948201945b838610156142175761420886614095565b825294820194908201906141f7565b96505086013592505080821115614172575f80fd5b805160ff811681146140ab575f80fd5b5f6020828403121561424c575f80fd5b61405f8261422c565b5f60208284031215614265575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156142935761429361426c565b92915050565b5f602082840312156142a9575f80fd5b8151801515811461405f575f80fd5b634e487b7160e01b5f52603260045260245ffd5b808201808211156142935761429361426c565b5f602082840312156142ef575f80fd5b815163ffffffff8116811461405f575f80fd5b80516bffffffffffffffffffffffff811681146140ab575f80fd5b5f6080828403121561432d575f80fd5b6040516080810181811067ffffffffffffffff8211171561435057614350613c4d565b60405261435c83614302565b815261436a60208401614302565b6020820152604083015161ffff81168114614383575f80fd5b60408201526143946060840161422c565b60608201529392505050565b5f80604083850312156143b1575f80fd5b505080516020909101519092909150565b80820281158282048414176142935761429361426c565b634e487b7160e01b5f52601260045260245ffd5b5f826143fb576143fb6143d9565b500490565b600181815b8085111561443a57815f19048211156144205761442061426c565b8085161561442d57918102915b93841c9390800290614405565b509250929050565b5f8261445057506001614293565b8161445c57505f614293565b8160018114614472576002811461447c57614498565b6001915050614293565b60ff84111561448d5761448d61426c565b50506001821b614293565b5060208310610133831016604e8410600b84101617156144bb575081810a614293565b6144c58383614400565b805f19048211156144d8576144d861426c565b029392505050565b5f61405f8383614442565b5f815180845260208085019450602084015f5b8381101561451a578151875295820195908201906001016144fe565b509495945050505050565b6001600160a01b0384168152606060208201525f61454660608301856144eb565b828103604084015261455881856144eb565b9695505050505050565b5f815180845260208085019450602084015f5b8381101561451a5781516001600160a01b031687529582019590820190600101614575565b604081525f6145ac6040830185614562565b82810360208401526145be81856144eb565b95945050505050565b5f67ffffffffffffffff808416806145e1576145e16143d9565b92169190910492915050565b67ffffffffffffffff82811682821603908082111561460e5761460e61426c565b5092915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0385168152836020820152608060408201525f61466a6080830185614615565b905082606083015295945050505050565b848152836020820152608060408201525f61466a6080830185614615565b5f600182016146aa576146aa61426c565b5060010190565b608081525f6146c36080830187614562565b82810360208401526146d581876144eb565b905082810360408401526146e98186614615565b91505082606083015295945050505050565b608080825285519082018190525f9060209060a0840190828901845b8281101561473357815184529284019290840190600101614717565b505050838103602085015261474881886144eb565b91505082810360408401526146e9818661461556fea2646970667358221220d5ad21b1e3c7f46f079be5de02f8abed25c59cb8c181f76db5750438335cf60864736f6c63430008190033", - "deployedBytecode": "0x6080604052600436106101da575f3560e01c806379bc81dd116100fd578063bc7d5c5c11610092578063dcb5ccc411610062578063dcb5ccc4146105f9578063e09177781461062d578063e6be59e714610660578063f4da12ba14610693575f80fd5b8063bc7d5c5c14610568578063d529779314610587578063d7accbcc146105a6578063d8bf69bf146105da575f80fd5b80639649a35c116100cd5780639649a35c146104eb578063a5edd4fc146104ff578063a6f9dae11461051e578063bb78678f1461053d575f80fd5b806379bc81dd1461046e5780638513e77d1461048d5780638833c205146104b85780638da5cb5b146104cc575f80fd5b80633c18d1dd1161017357806361d027b31161014357806361d027b3146103d257806363096509146103f157806363c4d28e14610410578063777e49c91461042f575f80fd5b80633c18d1dd146103345780634ac7251d146103675780635a55a482146103865780635c975abb146103a5575f80fd5b80632ad923dc116101ae5780632ad923dc146102cc5780632c0f3f29146102f757806334be5af41461030c5780633907196c14610321575f80fd5b806231d115146101de5780630d17db111461022e5780630d3241ee1461026c5780632a3bb6931461028b575b5f80fd5b3480156101e9575f80fd5b506102117f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b348015610239575f80fd5b5061025c610248366004613c36565b600a6020525f908152604090205460ff1681565b6040519015158152602001610225565b348015610277575f80fd5b50600554610211906001600160a01b031681565b348015610296575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610225565b3480156102d7575f80fd5b506102be6102e6366004613c36565b60066020525f908152604090205481565b61030a610305366004613cfe565b6106a7565b005b348015610317575f80fd5b506102be60015481565b61030a61032f366004613e5e565b610be6565b34801561033f575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b348015610372575f80fd5b50600354610211906001600160a01b031681565b348015610391575f80fd5b5061030a6103a0366004613fde565b611148565b3480156103b0575f80fd5b506002546103c590600160a81b900460ff1681565b604051610225919061401b565b3480156103dd575f80fd5b50600454610211906001600160a01b031681565b3480156103fc575f80fd5b5061030a61040b366004614041565b611312565b34801561041b575f80fd5b5061030a61042a366004613c36565b6113d1565b34801561043a575f80fd5b5061044e610449366004614066565b611654565b604080519485526020850193909352918301526060820152608001610225565b348015610479575f80fd5b5061030a610488366004613fde565b611b99565b348015610498575f80fd5b506102be6104a7366004613c36565b60076020525f908152604090205481565b3480156104c3575f80fd5b506102be5f5481565b3480156104d7575f80fd5b50600254610211906001600160a01b031681565b3480156104f6575f80fd5b5061030a611ca8565b34801561050a575f80fd5b5061030a610519366004613c36565b61204a565b348015610529575f80fd5b5061030a6105383660046140b0565b6121ed565b348015610548575f80fd5b506102be610557366004613c36565b60096020525f908152604090205481565b348015610573575f80fd5b5061030a6105823660046140c9565b6122aa565b348015610592575f80fd5b5061030a6105a13660046140e9565b61235a565b3480156105b1575f80fd5b506105c56105c0366004614129565b6124c8565b60408051928352602083019190915201610225565b3480156105e5575f80fd5b5061030a6105f4366004614189565b6128f9565b348015610604575f80fd5b50610211610613366004613c36565b60086020525f90815260409020546001600160a01b031681565b348015610638575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b34801561066b575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b34801561069e575f80fd5b506102be612a5c565b6002546001600160a01b90910460ff1611156106d6576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b1790555f83900361070a57604051637c946ed760e01b815260040160405180910390fd5b5f82900361072b5760405163d92e233d60e01b815260040160405180910390fd5b5f548085111561075d57604051637ae5968560e01b815260048101869052602481018290526044015b60405180910390fd5b60028054600160a81b900460ff169081600381111561077e5761077e614007565b148061079b5750600381600381111561079957610799614007565b145b8061081257506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af11580156107e7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061080b919061423c565b60ff166002145b15610830576040516313d0ff5960e31b815260040160405180910390fd5b5f8581526008602090815260408083205481517fa8b2ae0200000000000000000000000000000000000000000000000000000000815291516001600160a01b039091169392849263a8b2ae0292600480830193928290030181865afa15801561089b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108bf9190614255565b90505f805f806108d18c8c8c88611654565b5f81815260066020526040902082905592965090945092509050821561094b57600354604051635e148f0960e11b8152600481018590526001600160a01b039091169063bc291e12906024015f604051808303815f87803b158015610934575f80fd5b505af1158015610946573d5f803e3d5ffd5b505050505b5f8415610b8157505f8b815260096020526040902054849080156109a5578181106109845761097a8282614280565b90505f9150610994565b61098e8183614280565b91505f90505b5f8d81526009602052604090208190555b8115610b72576040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610a0f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a339190614255565b60048054604051637ff796ab60e01b815230928101929092525f6024830152604482018690529192506001600160a01b0390911690637ff796ab906064016020604051808303815f875af1158015610a8d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ab19190614299565b506040516370a0823160e01b815230600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610b16573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3a9190614255565b610b449190614280565b9050828114610b705760405163312b003360e01b81526004810182905260248101849052604401610754565b505b610b7f8d8d888e86612a88565b505b604080518681526020810183905290810185905233907f02b21954a7bf2d6a171db9a87b430a3723605c554db00adcb95b26ce8464f2809060600160405180910390a250506002805460ff60a01b1916600160a01b1790555050505050505050505050565b6002546001600160a01b90910460ff161115610c15576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b179055610c3484848484612c86565b5f5480861115610c6157604051637ae5968560e01b81526004810187905260248101829052604401610754565b60028054600160a81b900460ff1690816003811115610c8257610c82614007565b1480610c9f57506003816003811115610c9d57610c9d614007565b145b80610d1657506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af1158015610ceb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d0f919061423c565b60ff166002145b15610d34576040516313d0ff5960e31b815260040160405180910390fd5b6060806060610d448a8a8a612f84565b825192955090935091505f9084906002908110610d6357610d636142b8565b60200260200101511115610def5760035483516001600160a01b039091169063bc291e129085906002908110610d9b57610d9b6142b8565b60200260200101516040518263ffffffff1660e01b8152600401610dc191815260200190565b5f604051808303815f87803b158015610dd8575f80fd5b505af1158015610dea573d5f803e3d5ffd5b505050505b5f835f81518110610e0257610e026142b8565b60200260200101511115611086575f83600181518110610e2457610e246142b8565b60200260200101511115611078576040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610e96573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610eba9190614255565b60045485519192506001600160a01b031690637ff796ab9030905f9088906001908110610ee957610ee96142b8565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b039093166004840152602483019190915260448201526064016020604051808303815f875af1158015610f5c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f809190614299565b506040516370a0823160e01b815230600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610fe5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110099190614255565b6110139190614280565b905083600181518110611028576110286142b8565b6020026020010151811461107657808460018151811061104a5761104a6142b8565b602002602001015160405163312b003360e01b8152600401610754929190918252602082015260400190565b505b6110868989848a858b6134de565b336001600160a01b03167f02b21954a7bf2d6a171db9a87b430a3723605c554db00adcb95b26ce8464f280845f815181106110c3576110c36142b8565b6020026020010151856001815181106110de576110de6142b8565b6020026020010151866002815181106110f9576110f96142b8565b6020026020010151604051611121939291909283526020830191909152604082015260600190565b60405180910390a250506002805460ff60a01b1916600160a01b1790555050505050505050565b6002546001600160a01b031633146111885760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b821580611193575081155b8061119c575080155b156111ba57604051637c946ed760e01b815260040160405180910390fd5b4683036111dd57604051633881b68960e01b815260048101849052602401610754565b5f838152600960205260408120546111f69084906142cc565b90506bffffffffffffffffffffffff81111561123a57604051637ae5968560e01b8152600481018290526bffffffffffffffffffffffff6024820152604401610754565b5f8481526009602090815260408083208490556008909152908190205490517fac65ded2000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b0390911690819063ac65ded2906024015f604051808303815f87803b1580156112b1575f80fd5b505af11580156112c3573d5f803e3d5ffd5b505060408051888152602081018890529081018590528592507f2192822efd68ddf583804c65675b73a59694e672cab1758eb6714613f932a97591506060015b60405180910390a25050505050565b6002546001600160a01b031633146113525760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b600280548291907fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff16600160a81b83600381111561139257611392614007565b02179055507fa814f27828c0243d429ea8c7033cb10f0c825b9466fdc04f63e0cca26c28eb8a816040516113c6919061401b565b60405180910390a150565b6005546001600160a01b031633146114115760055460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610754565b807f00000000000000000000000000000000000000000000000000000000000000000361147357604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b600354604080517f14b19c5a00000000000000000000000000000000000000000000000000000000815290515f926001600160a01b0316916314b19c5a9160048083019260209291908290030181865afa1580156114d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114f791906142df565b60035463ffffffff9190911691505f906001600160a01b031663d4ee9f8d611520600185614280565b6040518263ffffffff1660e01b815260040161153e91815260200190565b602060405180830381865afa158015611559573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061157d9190614255565b90505f60035f9054906101000a90046001600160a01b03166001600160a01b031663d2b3996f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115d0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115f491906142df565b63ffffffff1690505f62093a8061160b83856142cc565b6116159190614280565b905080421061164057604051637ae5968560e01b815242600482015260248101829052604401610754565b5050505f9182526007602052604090912055565b5f805f80865f0361167857604051637c946ed760e01b815260040160405180910390fd5b5f8690036116995760405163d92e233d60e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000086036116fb57604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b5060408051808201825286815260209081018881528251808301899052905181840152825180820384018152606090910190925281519101205f61173f828a613ae7565b6005546040516317d5e89d60e31b8152600481018b9052602481018c90529195509192506001600160a01b039091169063beaf44e8906044015f604051808303815f87803b15801561178f575f80fd5b505af11580156117a1573d5f803e3d5ffd5b5083925050505b83811015611b8c575f818152600a602052604090205460ff16611b8457600354604051631ddf133560e01b8152600481018390525f916001600160a01b031690631ddf133590602401608060405180830381865afa15801561180c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611830919061431d565b606081015190915060ff16156118cf57604081015161ffff16158015611866575060208101516bffffffffffffffffffffffff16155b156118ca5761ffff7f00000000000000000000000000000000000000000000000000000000000000001660408201526bffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660208201525b6118d5565b50611b84565b60035460405163d4ee9f8d60e01b8152600481018490525f916001600160a01b03169063d4ee9f8d90602401602060405180830381865afa15801561191c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119409190614255565b600554604051630c88d47f60e41b8152600481018d9052602481018e9052604481018390529192505f9182916001600160a01b03169063c88d47f0906064016040805180830381865afa158015611999573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119bd91906143a0565b91509150805f03611a05575f858152600a60205260409020805460ff1916600117905583516119fa906bffffffffffffffffffffffff168a6142cc565b985050505050611b84565b83515f9081906bffffffffffffffffffffffff168184821115611a3257611a2c8583614280565b90508491505b6040880151611a4b9061ffff16655af3107a40006143c2565b861015611a8157670de0b6b3a764000086611a6684846142cc565b611a7091906143c2565b611a7a91906143ed565b9250611b6f565b670de0b6b3a7640000611a9487846143c2565b611a9e91906143ed565b9350670de0b6b3a7640000611ab387836143c2565b611abd91906143ed565b925087602001516bffffffffffffffffffffffff16915081841115611af657611ae68285614280565b611af090846142cc565b92508193505b60128f1015611b62575f8f6012611b0d9190614280565b611b1890600a6144e0565b611b2290866143ed565b90508f6012611b319190614280565b611b3c90600a6144e0565b611b4690826143c2565b9050611b528186614280565b611b5c90856142cc565b90945092505b611b6c848f6142cc565b9d505b611b79838e6142cc565b9c5050505050505050505b6001016117a8565b5050945094509450949050565b5f838152600860205260409020546001600160a01b0316338114611bfa576040517fdeeeedec0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0382166024820152604401610754565b5f84815260096020526040812054611c139085906142cc565b90506bffffffffffffffffffffffff811115611c5757604051637ae5968560e01b8152600481018290526bffffffffffffffffffffffff6024820152604401610754565b5f85815260096020908152604091829020839055815187815290810186905290810182905283907f2192822efd68ddf583804c65675b73a59694e672cab1758eb6714613f932a97590606001611303565b6002546001600160a01b90910460ff161115611cd7576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b1790555f80548190611d1a907f000000000000000000000000000000000000000000000000000000000000000090613ae7565b6005546040516317d5e89d60e31b81527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201529294509092506001600160a01b03169063beaf44e8906044015f604051808303815f87803b158015611d86575f80fd5b505af1158015611d98573d5f803e3d5ffd5b50507f00000000000000000000000000000000000000000000000000000000000000005f90815260066020526040812084905591508390505b82811015611f8857600354604051631ddf133560e01b8152600481018390525f916001600160a01b031690631ddf133590602401608060405180830381865afa158015611e20573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e44919061431d565b60035460405163d4ee9f8d60e01b8152600481018590529192505f916001600160a01b039091169063d4ee9f8d90602401602060405180830381865afa158015611e90573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611eb49190614255565b600554604051630c88d47f60e41b81527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604481018390529192505f916001600160a01b039091169063c88d47f0906064016040805180830381865afa158015611f2b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f4f91906143a0565b508351909150611f6e9082906bffffffffffffffffffffffff166143c2565b611f7890866142cc565b9450505050806001019050611dd1565b50611f9b670de0b6b3a7640000826143ed565b90508015611ffd57600354604051635e148f0960e11b8152600481018390526001600160a01b039091169063bc291e12906024015f604051808303815f87803b158015611fe6575f80fd5b505af1158015611ff8573d5f803e3d5ffd5b505050505b60405181815233907f2a8de497d698d6869cb0844411788378e76214d03a541eec6ba514b795d9f42e9060200160405180910390a250506002805460ff60a01b1916600160a01b17905550565b6005546001600160a01b0316331461208a5760055460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610754565b60028054600160a81b900460ff16908160038111156120ab576120ab614007565b14806120c8575060038160038111156120c6576120c6614007565b145b8061213f57506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af1158015612114573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612138919061423c565b60ff166002145b1561215d576040516313d0ff5960e31b815260040160405180910390fd5b60035f9054906101000a90046001600160a01b03166001600160a01b03166314b19c5a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121ad573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121d191906142df565b5f9283526006602052604090922063ffffffff90921690915550565b6002546001600160a01b0316331461222d5760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b6001600160a01b0381166122545760405163d92e233d60e01b815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f4ffd725fc4a22075e9ec71c59edf9c38cdeb588a91b24fc5b61388c5be41282b905f90a250565b6002546001600160a01b031633146122ea5760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b8115806122f5575080155b1561231357604051637c946ed760e01b815260040160405180910390fd5b5f829055600181905560408051838152602081018390527f61f6c4cc9665a257352c0b46189ffc2ae6fbbc11e155ff20901217ff203a517e91015b60405180910390a15050565b6002546001600160a01b0316331461239a5760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b6001600160a01b038316156123fd576003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0385169081179091556040517f4672fe7e13cfb163442d0b729b5733fb3efafc66cbe3677eac9940eb41c284c2905f90a25b6001600160a01b03821615612460576004805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384169081179091556040517f7dae230f18360d76a040c81f050aa14eb9d6dc7901b20fc5d855e2a20fe814d1905f90a25b6001600160a01b038116156124c3576005805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f04a606379838ed6fc83fd189eea9d1835b5eff05035c4b74622911ea2ae6b217905f90a25b505050565b5f806001600260149054906101000a900460ff1660ff1611156124fe576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b179081905560ff600160a81b90910416600181600381111561253257612532614007565b148061254f5750600381600381111561254d5761254d614007565b145b806125c657506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af115801561259b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125bf919061423c565b60ff166002145b156125e4576040516313d0ff5960e31b815260040160405180910390fd5b6003546040517f2e070f540000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690632e070f549061263190339089908990600401614525565b60408051808303815f875af115801561264c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061267091906143a0565b90935091505f8061268184866142cc565b1115612859575f8315612717576040516370a0823160e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156126f0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127149190614255565b90505b60048054604051637ff796ab60e01b8152339281019290925260248201879052604482018690526001600160a01b031690637ff796ab906064016020604051808303815f875af115801561276d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127919190614299565b91508315612857576040516370a0823160e01b815233600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156127fd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128219190614255565b61282b9190614280565b90508381146128575760405163312b003360e01b81526004810182905260248101859052604401610754565b505b806128a0576040517f942dc9da0000000000000000000000000000000000000000000000000000000081523360048201526024810185905260448101849052606401610754565b604080518581526020810185905233917f928890dff971de1394b7440848938a868d83445d2f7fb4b07938ae626c7cb130910160405180910390a250506002805460ff60a01b1916600160a01b17905590939092509050565b6002546001600160a01b031633146129395760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b8151158061294957508051825114155b1561297457815181516040516308151c1160e41b815260048101929092526024820152604401610754565b5f5b8151811015612a2a57818181518110612991576129916142b8565b60200260200101515f036129b857604051637c946ed760e01b815260040160405180910390fd5b8281815181106129ca576129ca6142b8565b602002602001015160085f8484815181106129e7576129e76142b8565b602002602001015181526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550806001019050612976565b507fe87460f6c400fa0166984512586d7bdf03a3230bbadf9651f27f08716dd77fa5828260405161234e92919061459a565b6024612a71600267ffffffffffffffff6145c7565b612a7b91906145ed565b67ffffffffffffffff1681565b5f858152600860205260409020546001600160a01b03168115612b50576040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b038281166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303815f875af1158015612b2a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b4e9190614299565b505b6024612b65600267ffffffffffffffff6145c7565b612b6f91906145ed565b67ffffffffffffffff168611612c02576040517fb2267a7b00000000000000000000000000000000000000000000000000000000815285906001600160a01b0383169063b2267a7b903490612bce9085908a908a908a90600401614643565b5f604051808303818588803b158015612be5575f80fd5b505af1158015612bf7573d5f803e3d5ffd5b505050505050612c7e565b6040517f6585ecdc0000000000000000000000000000000000000000000000000000000081526001600160a01b03821690636585ecdc903490612c4f90899089908990899060040161467b565b5f604051808303818588803b158015612c66575f80fd5b505af1158015612c78573d5f803e3d5ffd5b50505050505b505050505050565b8251845114612cb557835183516040516308151c1160e41b815260048101929092526024820152604401610754565b8151845114612ce457835182516040516308151c1160e41b815260048101929092526024820152604401610754565b8051845114612d1357835181516040516308151c1160e41b815260048101929092526024820152604401610754565b5f805f5b8651811015612f5a57868181518110612d3257612d326142b8565b60200260200101518310612d7657868181518110612d5257612d526142b8565b6020026020010151604051633881b68960e01b815260040161075491815260200190565b868181518110612d8857612d886142b8565b60200260200101519250858181518110612da457612da46142b8565b6020026020010151515f03612dcc57604051637c946ed760e01b815260040160405180910390fd5b838181518110612dde57612dde6142b8565b602002602001015182612df191906142cc565b91505f600154905080878381518110612e0c57612e0c6142b8565b6020026020010151511115612e5b57868281518110612e2d57612e2d6142b8565b60200260200101515181604051637ae5968560e01b8152600401610754929190918252602082015260400190565b5f805b888481518110612e7057612e706142b8565b602002602001015151811015612f4c57888481518110612e9257612e926142b8565b60200260200101518181518110612eab57612eab6142b8565b60200260200101515f1c825f1c10612f0c57888481518110612ecf57612ecf6142b8565b60200260200101518181518110612ee857612ee86142b8565b6020026020010151604051636aba776560e11b815260040161075491815260200190565b888481518110612f1e57612f1e6142b8565b60200260200101518181518110612f3757612f376142b8565b60200260200101519150806001019050612e5e565b505050806001019050612d17565b50803414612c7e5760405163312b003360e01b815234600482015260248101829052604401610754565b6040805160038082526080820190925260609182918291602082018380368337019050509250845167ffffffffffffffff811115612fc457612fc4613c4d565b604051908082528060200260200182016040528015612ff757816020015b6060815260200190600190039081612fe25790505b509150845167ffffffffffffffff81111561301457613014613c4d565b60405190808252806020026020018201604052801561303d578160200160208202803683370190505b5090505f5b85518110156134d4575f60085f888481518110613061576130616142b8565b602002602001015181526020019081526020015f205f9054906101000a90046001600160a01b031690505f816001600160a01b031663a8b2ae026040518163ffffffff1660e01b8152600401602060405180830381865afa1580156130c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130ec9190614255565b9050868381518110613100576131006142b8565b60200260200101515167ffffffffffffffff81111561312157613121613c4d565b60405190808252806020026020018201604052801561314a578160200160208202803683370190505b5085848151811061315d5761315d6142b8565b60200260200101819052505f5b87848151811061317c5761317c6142b8565b602002602001015151811015613363577f00000000000000000000000000000000000000000000000000000000000000008885815181106131bf576131bf6142b8565b602002602001015182815181106131d8576131d86142b8565b60200260200101510361322057604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b5f805f8061327b8e8e8a8151811061323a5761323a6142b8565b60200260200101518e8b81518110613254576132546142b8565b6020026020010151888151811061326d5761326d6142b8565b602002602001015189611654565b5f8181526006602052604090208290558d519397509195509350915084908b908a9081106132ab576132ab6142b8565b602002602001015186815181106132c4576132c46142b8565b602002602001018181525050838989815181106132e3576132e36142b8565b602002602001018181516132f791906142cc565b9052508a5184908c905f9061330e5761330e6142b8565b6020026020010181815161332291906142cc565b9052508a5183908c90600290811061333c5761333c6142b8565b6020026020010181815161335091906142cc565b905250506001909301925061316a915050565b505f848481518110613377576133776142b8565b60200260200101511115613486575f60095f8a868151811061339b5761339b6142b8565b602002602001015181526020019081526020015f205490505f811115613484578484815181106133cd576133cd6142b8565b60200260200101518110613426578484815181106133ed576133ed6142b8565b6020026020010151816134009190614280565b90505f858581518110613415576134156142b8565b602002602001018181525050613454565b80858581518110613439576134396142b8565b6020026020010181815161344d9190614280565b9052505f90505b8060095f8b878151811061346a5761346a6142b8565b602002602001015181526020019081526020015f20819055505b505b838381518110613498576134986142b8565b6020026020010151866001815181106134b3576134b36142b8565b602002602001018181516134c791906142cc565b9052505050600101613042565b5093509350939050565b5f5b8651811015613ade575f60085f8984815181106134ff576134ff6142b8565b602002602001015181526020019081526020015f205f9054906101000a90046001600160a01b031690505f84838151811061353c5761353c6142b8565b60200260200101511115613607577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb8286858151811061358c5761358c6142b8565b60200260200101516040518363ffffffff1660e01b81526004016135c59291906001600160a01b03929092168252602082015260400190565b6020604051808303815f875af11580156135e1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136059190614299565b505b5f8088848151811061361b5761361b6142b8565b60200260200101515167ffffffffffffffff81111561363c5761363c613c4d565b604051908082528060200260200182016040528015613665578160200160208202803683370190505b5090505f5b89858151811061367c5761367c6142b8565b6020026020010151518110156136fe575f89868151811061369f5761369f6142b8565b602002602001015182815181106136b8576136b86142b8565b602002602001015111156136f65760018282815181106136da576136da6142b8565b911515602092830291909101909101526136f383614699565b92505b60010161366a565b505f8267ffffffffffffffff81111561371957613719613c4d565b604051908082528060200260200182016040528015613742578160200160208202803683370190505b5090505f8367ffffffffffffffff81111561375f5761375f613c4d565b604051908082528060200260200182016040528015613788578160200160208202803683370190505b5090505f805b8c88815181106137a0576137a06142b8565b602002602001015151811015613884578481815181106137c2576137c26142b8565b60200260200101511561387c578c88815181106137e1576137e16142b8565b602002602001015181815181106137fa576137fa6142b8565b6020026020010151848381518110613814576138146142b8565b6020026020010181815250508b8881518110613832576138326142b8565b6020026020010151818151811061384b5761384b6142b8565b6020026020010151838381518110613865576138656142b8565b602090810291909101015261387982614699565b91505b60010161378e565b50602461389a600267ffffffffffffffff6145c7565b6138a491906145ed565b67ffffffffffffffff168d88815181106138c0576138c06142b8565b602002602001015111613a20575f835167ffffffffffffffff8111156138e8576138e8613c4d565b604051908082528060200260200182016040528015613911578160200160208202803683370190505b5090505f5b845181101561396d57848181518110613931576139316142b8565b60200260200101515f1c82828151811061394d5761394d6142b8565b6001600160a01b0390921660209283029190910190910152600101613916565b50866001600160a01b031663bde526618a8a8151811061398f5761398f6142b8565b602002602001015183868f8d815181106139ab576139ab6142b8565b60200260200101518f8e815181106139c5576139c56142b8565b60200260200101516040518663ffffffff1660e01b81526004016139ec94939291906146b1565b5f604051808303818588803b158015613a03575f80fd5b505af1158015613a15573d5f803e3d5ffd5b505050505050613acd565b856001600160a01b03166355442b59898981518110613a4157613a416142b8565b602002602001015185858e8c81518110613a5d57613a5d6142b8565b60200260200101518e8d81518110613a7757613a776142b8565b60200260200101516040518663ffffffff1660e01b8152600401613a9e94939291906146fb565b5f604051808303818588803b158015613ab5575f80fd5b505af1158015613ac7573d5f803e3d5ffd5b50505050505b5050505050508060010190506134e0565b50505050505050565b5f805f60035f9054906101000a90046001600160a01b03166001600160a01b03166314b19c5a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613b3a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613b5e91906142df565b5f86815260066020526040812054945063ffffffff919091169150839003613b9957604051637c946ed760e01b815260040160405180910390fd5b808303613bce5782613bac600183614280565b604051637ae5968560e01b815260048101929092526024820152604401610754565b5f85815260076020526040902054600181118015613bec5750808410155b15613bfd5783613bac600183614280565b613c0785856142cc565b9250600181118015613c1857508083115b15613c21578092505b81831115613c2d578192505b50509250929050565b5f60208284031215613c46575f80fd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613c8a57613c8a613c4d565b604052919050565b5f82601f830112613ca1575f80fd5b813567ffffffffffffffff811115613cbb57613cbb613c4d565b613cce601f8201601f1916602001613c61565b818152846020838601011115613ce2575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f8060808587031215613d11575f80fd5b843593506020850135925060408501359150606085013567ffffffffffffffff811115613d3c575f80fd5b613d4887828801613c92565b91505092959194509250565b5f67ffffffffffffffff821115613d6d57613d6d613c4d565b5060051b60200190565b5f82601f830112613d86575f80fd5b81356020613d9b613d9683613d54565b613c61565b8083825260208201915060208460051b870101935086841115613dbc575f80fd5b602086015b84811015613dd85780358352918301918301613dc1565b509695505050505050565b5f82601f830112613df2575f80fd5b81356020613e02613d9683613d54565b82815260059290921b84018101918181019086841115613e20575f80fd5b8286015b84811015613dd857803567ffffffffffffffff811115613e42575f80fd5b613e508986838b0101613c92565b845250918301918301613e24565b5f805f805f60a08688031215613e72575f80fd5b8535945067ffffffffffffffff8060208801351115613e8f575f80fd5b613e9f8860208901358901613d77565b94508060408801351115613eb1575f80fd5b6040870135870188601f820112613ec6575f80fd5b613ed3613d968235613d54565b81358082526020808301929160051b8401018b1015613ef0575f80fd5b602083015b6020843560051b850101811015613f8a578481351115613f13575f80fd5b803584018c603f820112613f25575f80fd5b613f35613d966020830135613d54565b602082810135808352908201919060051b83016040018f811115613f57575f80fd5b6040840193505b80841015613f79578335835260209384019390920191613f5e565b508552505060209283019201613ef5565b50955050506060870135811015613f9f575f80fd5b613faf8860608901358901613de3565b92508060808801351115613fc1575f80fd5b50613fd28760808801358801613d77565b90509295509295909350565b5f805f60608486031215613ff0575f80fd5b505081359360208301359350604090920135919050565b634e487b7160e01b5f52602160045260245ffd5b602081016004831061403b57634e487b7160e01b5f52602160045260245ffd5b91905290565b5f60208284031215614051575f80fd5b81356004811061405f575f80fd5b9392505050565b5f805f8060808587031215614079575f80fd5b5050823594602084013594506040840135936060013592509050565b80356001600160a01b03811681146140ab575f80fd5b919050565b5f602082840312156140c0575f80fd5b61405f82614095565b5f80604083850312156140da575f80fd5b50508035926020909101359150565b5f805f606084860312156140fb575f80fd5b61410484614095565b925061411260208501614095565b915061412060408501614095565b90509250925092565b5f806040838503121561413a575f80fd5b823567ffffffffffffffff80821115614151575f80fd5b61415d86838701613d77565b93506020850135915080821115614172575f80fd5b5061417f85828601613d77565b9150509250929050565b5f806040838503121561419a575f80fd5b823567ffffffffffffffff808211156141b1575f80fd5b818501915085601f8301126141c4575f80fd5b813560206141d4613d9683613d54565b82815260059290921b840181019181810190898411156141f2575f80fd5b948201945b838610156142175761420886614095565b825294820194908201906141f7565b96505086013592505080821115614172575f80fd5b805160ff811681146140ab575f80fd5b5f6020828403121561424c575f80fd5b61405f8261422c565b5f60208284031215614265575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156142935761429361426c565b92915050565b5f602082840312156142a9575f80fd5b8151801515811461405f575f80fd5b634e487b7160e01b5f52603260045260245ffd5b808201808211156142935761429361426c565b5f602082840312156142ef575f80fd5b815163ffffffff8116811461405f575f80fd5b80516bffffffffffffffffffffffff811681146140ab575f80fd5b5f6080828403121561432d575f80fd5b6040516080810181811067ffffffffffffffff8211171561435057614350613c4d565b60405261435c83614302565b815261436a60208401614302565b6020820152604083015161ffff81168114614383575f80fd5b60408201526143946060840161422c565b60608201529392505050565b5f80604083850312156143b1575f80fd5b505080516020909101519092909150565b80820281158282048414176142935761429361426c565b634e487b7160e01b5f52601260045260245ffd5b5f826143fb576143fb6143d9565b500490565b600181815b8085111561443a57815f19048211156144205761442061426c565b8085161561442d57918102915b93841c9390800290614405565b509250929050565b5f8261445057506001614293565b8161445c57505f614293565b8160018114614472576002811461447c57614498565b6001915050614293565b60ff84111561448d5761448d61426c565b50506001821b614293565b5060208310610133831016604e8410600b84101617156144bb575081810a614293565b6144c58383614400565b805f19048211156144d8576144d861426c565b029392505050565b5f61405f8383614442565b5f815180845260208085019450602084015f5b8381101561451a578151875295820195908201906001016144fe565b509495945050505050565b6001600160a01b0384168152606060208201525f61454660608301856144eb565b828103604084015261455881856144eb565b9695505050505050565b5f815180845260208085019450602084015f5b8381101561451a5781516001600160a01b031687529582019590820190600101614575565b604081525f6145ac6040830185614562565b82810360208401526145be81856144eb565b95945050505050565b5f67ffffffffffffffff808416806145e1576145e16143d9565b92169190910492915050565b67ffffffffffffffff82811682821603908082111561460e5761460e61426c565b5092915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0385168152836020820152608060408201525f61466a6080830185614615565b905082606083015295945050505050565b848152836020820152608060408201525f61466a6080830185614615565b5f600182016146aa576146aa61426c565b5060010190565b608081525f6146c36080830187614562565b82810360208401526146d581876144eb565b905082810360408401526146e98186614615565b91505082606083015295945050505050565b608080825285519082018190525f9060209060a0840190828901845b8281101561473357815184529284019290840190600101614717565b505050838103602085015261474881886144eb565b91505082810360408401526146e9818661461556fea2646970667358221220d5ad21b1e3c7f46f079be5de02f8abed25c59cb8c181f76db5750438335cf60864736f6c63430008190033", + "bytecode": "0x610120604052348015610010575f80fd5b50604051614c6a380380614c6a83398101604081905261002f91610226565b6002805460ff60a01b1933166001600160a81b031990911617600160a01b1760ff60a81b1916600160a91b1790556001600160a01b038916158061007a57506001600160a01b038816155b8061008c57506001600160a01b038716155b8061009e57506001600160a01b038616155b806100a7575084155b156100c55760405163d92e233d60e01b815260040160405180910390fd5b8315806100d0575082155b806100d9575081155b806100e2575080155b1561010057604051637c946ed760e01b815260040160405180910390fd5b61ffff82111561013357604051637ae5968560e01b81526004810183905261ffff60248201526044015b60405180910390fd5b6001600160601b0381111561016b57604051637ae5968560e01b8152600481018290526001600160601b03602482015260440161012a565b6001600160a01b0398891660c05260038054988a166001600160a01b0319998a1617905560048054978a16978916979097179096556005805495909816949096169390931790955560e0819052604080518082018252828152466020918201908152825180830194909452518383015281518084038301815260609093019091528151910120610100525f9390935560019290925560805260a0526102a5565b80516001600160a01b0381168114610221575f80fd5b919050565b5f805f805f805f805f6101208a8c03121561023f575f80fd5b6102488a61020b565b985061025660208b0161020b565b975061026460408b0161020b565b965061027260608b0161020b565b955060808a0151945060a08a0151935060c08a0151925060e08a015191506101008a015190509295985092959850929598565b60805160a05160c05160e051610100516148fc61036e5f395f81816103450152818161141701528181611d220152611dc901525f81816106710152818161144a015281816116c8015281816116fc01528181611d5901528181611ef3015281816131f0015261325601525f81816101ef015281816109c201528181610ac901528181610e5701528181610fa6015281816126f90152818161280601528181612b4601526135ae01525f818161063e01526118d101525f818161029c015261189d01526148fc5ff3fe6080604052600436106101da575f3560e01c806379bc81dd116100fd578063bc7d5c5c11610092578063dcb5ccc411610062578063dcb5ccc4146105f9578063e09177781461062d578063e6be59e714610660578063f4da12ba14610693575f80fd5b8063bc7d5c5c14610568578063d529779314610587578063d7accbcc146105a6578063d8bf69bf146105da575f80fd5b80639649a35c116100cd5780639649a35c146104eb578063a5edd4fc146104ff578063a6f9dae11461051e578063bb78678f1461053d575f80fd5b806379bc81dd1461046e5780638513e77d1461048d5780638833c205146104b85780638da5cb5b146104cc575f80fd5b80633c18d1dd1161017357806361d027b31161014357806361d027b3146103d257806363096509146103f157806363c4d28e14610410578063777e49c91461042f575f80fd5b80633c18d1dd146103345780634ac7251d146103675780635a55a482146103865780635c975abb146103a5575f80fd5b80632ad923dc116101ae5780632ad923dc146102cc5780632c0f3f29146102f757806334be5af41461030c5780633907196c14610321575f80fd5b806231d115146101de5780630d17db111461022e5780630d3241ee1461026c5780632a3bb6931461028b575b5f80fd5b3480156101e9575f80fd5b506102117f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b348015610239575f80fd5b5061025c610248366004613ca3565b600a6020525f908152604090205460ff1681565b6040519015158152602001610225565b348015610277575f80fd5b50600554610211906001600160a01b031681565b348015610296575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610225565b3480156102d7575f80fd5b506102be6102e6366004613ca3565b60066020525f908152604090205481565b61030a610305366004613d6b565b6106a7565b005b348015610317575f80fd5b506102be60015481565b61030a61032f366004613ecb565b610bf4565b34801561033f575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b348015610372575f80fd5b50600354610211906001600160a01b031681565b348015610391575f80fd5b5061030a6103a036600461404b565b61114b565b3480156103b0575f80fd5b506002546103c590600160a81b900460ff1681565b6040516102259190614088565b3480156103dd575f80fd5b50600454610211906001600160a01b031681565b3480156103fc575f80fd5b5061030a61040b3660046140ae565b611315565b34801561041b575f80fd5b5061030a61042a366004613ca3565b6113d4565b34801561043a575f80fd5b5061044e6104493660046140d3565b611681565b604080519485526020850193909352918301526060820152608001610225565b348015610479575f80fd5b5061030a61048836600461404b565b611bc6565b348015610498575f80fd5b506102be6104a7366004613ca3565b60076020525f908152604090205481565b3480156104c3575f80fd5b506102be5f5481565b3480156104d7575f80fd5b50600254610211906001600160a01b031681565b3480156104f6575f80fd5b5061030a611cd5565b34801561050a575f80fd5b5061030a610519366004613ca3565b612077565b348015610529575f80fd5b5061030a61053836600461411d565b612243565b348015610548575f80fd5b506102be610557366004613ca3565b60096020525f908152604090205481565b348015610573575f80fd5b5061030a610582366004614136565b612300565b348015610592575f80fd5b5061030a6105a1366004614156565b6123b0565b3480156105b1575f80fd5b506105c56105c0366004614196565b61251e565b60408051928352602083019190915201610225565b3480156105e5575f80fd5b5061030a6105f43660046141f6565b61295b565b348015610604575f80fd5b50610211610613366004613ca3565b60086020525f90815260409020546001600160a01b031681565b348015610638575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b34801561066b575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b34801561069e575f80fd5b506102be612abe565b6002546001600160a01b90910460ff1611156106d6576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b1790555f83900361070a57604051637c946ed760e01b815260040160405180910390fd5b5f82900361072b5760405163d92e233d60e01b815260040160405180910390fd5b5f548085111561075d57604051637ae5968560e01b815260048101869052602481018290526044015b60405180910390fd5b60028054600160a81b900460ff169081600381111561077e5761077e614074565b148061079b5750600381600381111561079957610799614074565b145b8061081257506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af11580156107e7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061080b91906142a9565b60ff166002145b15610830576040516313d0ff5960e31b815260040160405180910390fd5b5f8581526008602090815260408083205481517fa8b2ae0200000000000000000000000000000000000000000000000000000000815291516001600160a01b039091169392849263a8b2ae0292600480830193928290030181865afa15801561089b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108bf91906142c2565b90505f805f806108d18c8c8c88611681565b5f81815260066020526040902082905592965090945092509050821561094b57600354604051635e148f0960e11b8152600481018590526001600160a01b039091169063bc291e12906024015f604051808303815f87803b158015610934575f80fd5b505af1158015610946573d5f803e3d5ffd5b505050505b5f8415610b8157505f8b815260096020526040902054849080156109a5578181106109845761097a82826142ed565b90505f9150610994565b61098e81836142ed565b91505f90505b5f8d81526009602052604090208190555b8115610b72576040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610a0f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a3391906142c2565b60048054604051637ff796ab60e01b815230928101929092525f6024830152604482018690529192506001600160a01b0390911690637ff796ab906064016020604051808303815f875af1158015610a8d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ab19190614306565b506040516370a0823160e01b815230600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610b16573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3a91906142c2565b610b4491906142ed565b9050828114610b705760405163312b003360e01b81526004810182905260248101849052604401610754565b505b610b7f8d8d888e86612aea565b505b604080518d8152602081018d9052908101869052606081018290526080810185905233907f4095040bd441bb6761c0f983f93688032932a70ea67c45acf217522134d0e90c9060a00160405180910390a250506002805460ff60a01b1916600160a01b1790555050505050505050505050565b6002546001600160a01b90910460ff161115610c23576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b179055610c4284848484612ce8565b5f5480861115610c6f57604051637ae5968560e01b81526004810187905260248101829052604401610754565b60028054600160a81b900460ff1690816003811115610c9057610c90614074565b1480610cad57506003816003811115610cab57610cab614074565b145b80610d2457506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af1158015610cf9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d1d91906142a9565b60ff166002145b15610d42576040516313d0ff5960e31b815260040160405180910390fd5b6060806060610d528a8a8a612fe6565b825192955090935091505f9084906002908110610d7157610d71614325565b60200260200101511115610dfd5760035483516001600160a01b039091169063bc291e129085906002908110610da957610da9614325565b60200260200101516040518263ffffffff1660e01b8152600401610dcf91815260200190565b5f604051808303815f87803b158015610de6575f80fd5b505af1158015610df8573d5f803e3d5ffd5b505050505b5f835f81518110610e1057610e10614325565b60200260200101511115611094575f83600181518110610e3257610e32614325565b60200260200101511115611086576040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610ea4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ec891906142c2565b60045485519192506001600160a01b031690637ff796ab9030905f9088906001908110610ef757610ef7614325565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b039093166004840152602483019190915260448201526064016020604051808303815f875af1158015610f6a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f8e9190614306565b506040516370a0823160e01b815230600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610ff3573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061101791906142c2565b61102191906142ed565b90508360018151811061103657611036614325565b6020026020010151811461108457808460018151811061105857611058614325565b602002602001015160405163312b003360e01b8152600401610754929190918252602082015260400190565b505b6110948989848a858b613540565b336001600160a01b03167f4e8f98bab2ce9f2ab5649073958662ae3277689fdf749865832601431e3153ac8a8a85875f815181106110d4576110d4614325565b6020026020010151886001815181106110ef576110ef614325565b60200260200101518960028151811061110a5761110a614325565b6020026020010151604051611124969594939291906143ee565b60405180910390a250506002805460ff60a01b1916600160a01b1790555050505050505050565b6002546001600160a01b0316331461118b5760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b821580611196575081155b8061119f575080155b156111bd57604051637c946ed760e01b815260040160405180910390fd5b4683036111e057604051633881b68960e01b815260048101849052602401610754565b5f838152600960205260408120546111f9908490614484565b90506bffffffffffffffffffffffff81111561123d57604051637ae5968560e01b8152600481018290526bffffffffffffffffffffffff6024820152604401610754565b5f8481526009602090815260408083208490556008909152908190205490517fac65ded2000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b0390911690819063ac65ded2906024015f604051808303815f87803b1580156112b4575f80fd5b505af11580156112c6573d5f803e3d5ffd5b505060408051888152602081018890529081018590528592507f2192822efd68ddf583804c65675b73a59694e672cab1758eb6714613f932a97591506060015b60405180910390a25050505050565b6002546001600160a01b031633146113555760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b600280548291907fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff16600160a81b83600381111561139557611395614074565b02179055507fa814f27828c0243d429ea8c7033cb10f0c825b9466fdc04f63e0cca26c28eb8a816040516113c99190614088565b60405180910390a150565b6005546001600160a01b031633146114145760055460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610754565b807f00000000000000000000000000000000000000000000000000000000000000000361147657604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b600354604080517f14b19c5a00000000000000000000000000000000000000000000000000000000815290515f926001600160a01b0316916314b19c5a9160048083019260209291908290030181865afa1580156114d6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114fa9190614497565b60035463ffffffff9190911691505f906001600160a01b031663d4ee9f8d6115236001856142ed565b6040518263ffffffff1660e01b815260040161154191815260200190565b602060405180830381865afa15801561155c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061158091906142c2565b90505f60035f9054906101000a90046001600160a01b03166001600160a01b031663d2b3996f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115f79190614497565b63ffffffff1690505f62093a8061160e8385614484565b61161891906142ed565b905080421061164357604051637ae5968560e01b815242600482015260248101829052604401610754565b5f858152600760205260408082208690555186917f5a6a4aed2babbf3fe4cddce74151568eaac96f250cf910532f6528b1f6ee13d891a25050505050565b5f805f80865f036116a557604051637c946ed760e01b815260040160405180910390fd5b5f8690036116c65760405163d92e233d60e01b815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000860361172857604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b5060408051808201825286815260209081018881528251808301899052905181840152825180820384018152606090910190925281519101205f61176c828a613b56565b6005546040516317d5e89d60e31b8152600481018b9052602481018c90529195509192506001600160a01b039091169063beaf44e8906044015f604051808303815f87803b1580156117bc575f80fd5b505af11580156117ce573d5f803e3d5ffd5b5083925050505b83811015611bb9575f818152600a602052604090205460ff16611bb157600354604051631ddf133560e01b8152600481018390525f916001600160a01b031690631ddf133590602401608060405180830381865afa158015611839573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061185d91906144d5565b606081015190915060ff16156118fc57604081015161ffff16158015611893575060208101516bffffffffffffffffffffffff16155b156118f75761ffff7f00000000000000000000000000000000000000000000000000000000000000001660408201526bffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660208201525b611902565b50611bb1565b60035460405163d4ee9f8d60e01b8152600481018490525f916001600160a01b03169063d4ee9f8d90602401602060405180830381865afa158015611949573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061196d91906142c2565b600554604051630c88d47f60e41b8152600481018d9052602481018e9052604481018390529192505f9182916001600160a01b03169063c88d47f0906064016040805180830381865afa1580156119c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119ea9190614558565b91509150805f03611a32575f858152600a60205260409020805460ff191660011790558351611a27906bffffffffffffffffffffffff168a614484565b985050505050611bb1565b83515f9081906bffffffffffffffffffffffff168184821115611a5f57611a5985836142ed565b90508491505b6040880151611a789061ffff16655af3107a400061457a565b861015611aae57670de0b6b3a764000086611a938484614484565b611a9d919061457a565b611aa791906145a5565b9250611b9c565b670de0b6b3a7640000611ac1878461457a565b611acb91906145a5565b9350670de0b6b3a7640000611ae0878361457a565b611aea91906145a5565b925087602001516bffffffffffffffffffffffff16915081841115611b2357611b1382856142ed565b611b1d9084614484565b92508193505b60128f1015611b8f575f8f6012611b3a91906142ed565b611b4590600a614698565b611b4f90866145a5565b90508f6012611b5e91906142ed565b611b6990600a614698565b611b73908261457a565b9050611b7f81866142ed565b611b899085614484565b90945092505b611b99848f614484565b9d505b611ba6838e614484565b9c5050505050505050505b6001016117d5565b5050945094509450949050565b5f838152600860205260409020546001600160a01b0316338114611c27576040517fdeeeedec0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0382166024820152604401610754565b5f84815260096020526040812054611c40908590614484565b90506bffffffffffffffffffffffff811115611c8457604051637ae5968560e01b8152600481018290526bffffffffffffffffffffffff6024820152604401610754565b5f85815260096020908152604091829020839055815187815290810186905290810182905283907f2192822efd68ddf583804c65675b73a59694e672cab1758eb6714613f932a97590606001611306565b6002546001600160a01b90910460ff161115611d04576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b1790555f80548190611d47907f000000000000000000000000000000000000000000000000000000000000000090613b56565b6005546040516317d5e89d60e31b81527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201529294509092506001600160a01b03169063beaf44e8906044015f604051808303815f87803b158015611db3575f80fd5b505af1158015611dc5573d5f803e3d5ffd5b50507f00000000000000000000000000000000000000000000000000000000000000005f90815260066020526040812084905591508390505b82811015611fb557600354604051631ddf133560e01b8152600481018390525f916001600160a01b031690631ddf133590602401608060405180830381865afa158015611e4d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e7191906144d5565b60035460405163d4ee9f8d60e01b8152600481018590529192505f916001600160a01b039091169063d4ee9f8d90602401602060405180830381865afa158015611ebd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ee191906142c2565b600554604051630c88d47f60e41b81527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604481018390529192505f916001600160a01b039091169063c88d47f0906064016040805180830381865afa158015611f58573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f7c9190614558565b508351909150611f9b9082906bffffffffffffffffffffffff1661457a565b611fa59086614484565b9450505050806001019050611dfe565b50611fc8670de0b6b3a7640000826145a5565b9050801561202a57600354604051635e148f0960e11b8152600481018390526001600160a01b039091169063bc291e12906024015f604051808303815f87803b158015612013575f80fd5b505af1158015612025573d5f803e3d5ffd5b505050505b60405181815233907f2a8de497d698d6869cb0844411788378e76214d03a541eec6ba514b795d9f42e9060200160405180910390a250506002805460ff60a01b1916600160a01b17905550565b6005546001600160a01b031633146120b75760055460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610754565b60028054600160a81b900460ff16908160038111156120d8576120d8614074565b14806120f5575060038160038111156120f3576120f3614074565b145b8061216c57506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af1158015612141573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061216591906142a9565b60ff166002145b1561218a576040516313d0ff5960e31b815260040160405180910390fd5b60035f9054906101000a90046001600160a01b03166001600160a01b03166314b19c5a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121da573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121fe9190614497565b5f8381526006602052604080822063ffffffff93909316909255905183917f5381b67b592d2dc84b61238222ab88ee04db3b3a082894a445c4e5cfa8ba11be91a25050565b6002546001600160a01b031633146122835760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b6001600160a01b0381166122aa5760405163d92e233d60e01b815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f4ffd725fc4a22075e9ec71c59edf9c38cdeb588a91b24fc5b61388c5be41282b905f90a250565b6002546001600160a01b031633146123405760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b81158061234b575080155b1561236957604051637c946ed760e01b815260040160405180910390fd5b5f829055600181905560408051838152602081018390527f61f6c4cc9665a257352c0b46189ffc2ae6fbbc11e155ff20901217ff203a517e91015b60405180910390a15050565b6002546001600160a01b031633146123f05760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b6001600160a01b03831615612453576003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0385169081179091556040517f4672fe7e13cfb163442d0b729b5733fb3efafc66cbe3677eac9940eb41c284c2905f90a25b6001600160a01b038216156124b6576004805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384169081179091556040517f7dae230f18360d76a040c81f050aa14eb9d6dc7901b20fc5d855e2a20fe814d1905f90a25b6001600160a01b03811615612519576005805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f04a606379838ed6fc83fd189eea9d1835b5eff05035c4b74622911ea2ae6b217905f90a25b505050565b5f806001600260149054906101000a900460ff1660ff161115612554576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b179081905560ff600160a81b90910416600181600381111561258857612588614074565b14806125a5575060038160038111156125a3576125a3614074565b145b8061261c57506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af11580156125f1573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061261591906142a9565b60ff166002145b1561263a576040516313d0ff5960e31b815260040160405180910390fd5b6003546040517f2e070f540000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690632e070f5490612687903390899089906004016146a3565b60408051808303815f875af11580156126a2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126c69190614558565b90935091505f806126d78486614484565b11156128af575f831561276d576040516370a0823160e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612746573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061276a91906142c2565b90505b60048054604051637ff796ab60e01b8152339281019290925260248201879052604482018690526001600160a01b031690637ff796ab906064016020604051808303815f875af11580156127c3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127e79190614306565b915083156128ad576040516370a0823160e01b815233600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612853573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061287791906142c2565b61288191906142ed565b90508381146128ad5760405163312b003360e01b81526004810182905260248101859052604401610754565b505b806128f6576040517f942dc9da0000000000000000000000000000000000000000000000000000000081523360048201526024810185905260448101849052606401610754565b336001600160a01b03167fbe9ae4aaa6e41ee5c966cad91e78ec7202d0062fe8c9564b28629a614003cf828585898960405161293594939291906146e0565b60405180910390a250506002805460ff60a01b1916600160a01b17905590939092509050565b6002546001600160a01b0316331461299b5760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b815115806129ab57508051825114155b156129d657815181516040516308151c1160e41b815260048101929092526024820152604401610754565b5f5b8151811015612a8c578181815181106129f3576129f3614325565b60200260200101515f03612a1a57604051637c946ed760e01b815260040160405180910390fd5b828181518110612a2c57612a2c614325565b602002602001015160085f848481518110612a4957612a49614325565b602002602001015181526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508060010190506129d8565b507fe87460f6c400fa0166984512586d7bdf03a3230bbadf9651f27f08716dd77fa582826040516123a4929190614753565b6024612ad3600267ffffffffffffffff614780565b612add91906147a6565b67ffffffffffffffff1681565b5f858152600860205260409020546001600160a01b03168115612bb2576040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b038281166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303815f875af1158015612b8c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bb09190614306565b505b6024612bc7600267ffffffffffffffff614780565b612bd191906147a6565b67ffffffffffffffff168611612c64576040517fb2267a7b00000000000000000000000000000000000000000000000000000000815285906001600160a01b0383169063b2267a7b903490612c309085908a908a908a906004016147fc565b5f604051808303818588803b158015612c47575f80fd5b505af1158015612c59573d5f803e3d5ffd5b505050505050612ce0565b6040517f6585ecdc0000000000000000000000000000000000000000000000000000000081526001600160a01b03821690636585ecdc903490612cb1908990899089908990600401614834565b5f604051808303818588803b158015612cc8575f80fd5b505af1158015612cda573d5f803e3d5ffd5b50505050505b505050505050565b8251845114612d1757835183516040516308151c1160e41b815260048101929092526024820152604401610754565b8151845114612d4657835182516040516308151c1160e41b815260048101929092526024820152604401610754565b8051845114612d7557835181516040516308151c1160e41b815260048101929092526024820152604401610754565b5f805f5b8651811015612fbc57868181518110612d9457612d94614325565b60200260200101518310612dd857868181518110612db457612db4614325565b6020026020010151604051633881b68960e01b815260040161075491815260200190565b868181518110612dea57612dea614325565b60200260200101519250858181518110612e0657612e06614325565b6020026020010151515f03612e2e57604051637c946ed760e01b815260040160405180910390fd5b838181518110612e4057612e40614325565b602002602001015182612e539190614484565b91505f600154905080878381518110612e6e57612e6e614325565b6020026020010151511115612ebd57868281518110612e8f57612e8f614325565b60200260200101515181604051637ae5968560e01b8152600401610754929190918252602082015260400190565b5f805b888481518110612ed257612ed2614325565b602002602001015151811015612fae57888481518110612ef457612ef4614325565b60200260200101518181518110612f0d57612f0d614325565b60200260200101515f1c825f1c10612f6e57888481518110612f3157612f31614325565b60200260200101518181518110612f4a57612f4a614325565b6020026020010151604051636aba776560e11b815260040161075491815260200190565b888481518110612f8057612f80614325565b60200260200101518181518110612f9957612f99614325565b60200260200101519150806001019050612ec0565b505050806001019050612d79565b50803414612ce05760405163312b003360e01b815234600482015260248101829052604401610754565b6040805160038082526080820190925260609182918291602082018380368337019050509250845167ffffffffffffffff81111561302657613026613cba565b60405190808252806020026020018201604052801561305957816020015b60608152602001906001900390816130445790505b509150845167ffffffffffffffff81111561307657613076613cba565b60405190808252806020026020018201604052801561309f578160200160208202803683370190505b5090505f5b8551811015613536575f60085f8884815181106130c3576130c3614325565b602002602001015181526020019081526020015f205f9054906101000a90046001600160a01b031690505f816001600160a01b031663a8b2ae026040518163ffffffff1660e01b8152600401602060405180830381865afa15801561312a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061314e91906142c2565b905086838151811061316257613162614325565b60200260200101515167ffffffffffffffff81111561318357613183613cba565b6040519080825280602002602001820160405280156131ac578160200160208202803683370190505b508584815181106131bf576131bf614325565b60200260200101819052505f5b8784815181106131de576131de614325565b6020026020010151518110156133c5577f000000000000000000000000000000000000000000000000000000000000000088858151811061322157613221614325565b6020026020010151828151811061323a5761323a614325565b60200260200101510361328257604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b5f805f806132dd8e8e8a8151811061329c5761329c614325565b60200260200101518e8b815181106132b6576132b6614325565b602002602001015188815181106132cf576132cf614325565b602002602001015189611681565b5f8181526006602052604090208290558d519397509195509350915084908b908a90811061330d5761330d614325565b6020026020010151868151811061332657613326614325565b6020026020010181815250508389898151811061334557613345614325565b602002602001018181516133599190614484565b9052508a5184908c905f9061337057613370614325565b602002602001018181516133849190614484565b9052508a5183908c90600290811061339e5761339e614325565b602002602001018181516133b29190614484565b90525050600190930192506131cc915050565b505f8484815181106133d9576133d9614325565b602002602001015111156134e8575f60095f8a86815181106133fd576133fd614325565b602002602001015181526020019081526020015f205490505f8111156134e65784848151811061342f5761342f614325565b602002602001015181106134885784848151811061344f5761344f614325565b60200260200101518161346291906142ed565b90505f85858151811061347757613477614325565b6020026020010181815250506134b6565b8085858151811061349b5761349b614325565b602002602001018181516134af91906142ed565b9052505f90505b8060095f8b87815181106134cc576134cc614325565b602002602001015181526020019081526020015f20819055505b505b8383815181106134fa576134fa614325565b60200260200101518660018151811061351557613515614325565b602002602001018181516135299190614484565b90525050506001016130a4565b5093509350939050565b5f5b8651811015613b4d575f60085f89848151811061356157613561614325565b602002602001015181526020019081526020015f205f9054906101000a90046001600160a01b031690505f84838151811061359e5761359e614325565b60200260200101511115613669577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb828685815181106135ee576135ee614325565b60200260200101516040518363ffffffff1660e01b81526004016136279291906001600160a01b03929092168252602082015260400190565b6020604051808303815f875af1158015613643573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136679190614306565b505b5f8088848151811061367d5761367d614325565b60200260200101515167ffffffffffffffff81111561369e5761369e613cba565b6040519080825280602002602001820160405280156136c7578160200160208202803683370190505b5090505f5b8985815181106136de576136de614325565b602002602001015151811015613760575f89868151811061370157613701614325565b6020026020010151828151811061371a5761371a614325565b6020026020010151111561375857600182828151811061373c5761373c614325565b9115156020928302919091019091015261375583614852565b92505b6001016136cc565b50815f0361377057505050613b45565b5f8267ffffffffffffffff81111561378a5761378a613cba565b6040519080825280602002602001820160405280156137b3578160200160208202803683370190505b5090505f8367ffffffffffffffff8111156137d0576137d0613cba565b6040519080825280602002602001820160405280156137f9578160200160208202803683370190505b5090505f805b8c888151811061381157613811614325565b6020026020010151518110156138f55784818151811061383357613833614325565b6020026020010151156138ed578c888151811061385257613852614325565b6020026020010151818151811061386b5761386b614325565b602002602001015184838151811061388557613885614325565b6020026020010181815250508b88815181106138a3576138a3614325565b602002602001015181815181106138bc576138bc614325565b60200260200101518383815181106138d6576138d6614325565b60209081029190910101526138ea82614852565b91505b6001016137ff565b50602461390b600267ffffffffffffffff614780565b61391591906147a6565b67ffffffffffffffff168d888151811061393157613931614325565b602002602001015111613a91575f835167ffffffffffffffff81111561395957613959613cba565b604051908082528060200260200182016040528015613982578160200160208202803683370190505b5090505f5b84518110156139de578481815181106139a2576139a2614325565b60200260200101515f1c8282815181106139be576139be614325565b6001600160a01b0390921660209283029190910190910152600101613987565b50866001600160a01b031663bde526618a8a81518110613a0057613a00614325565b602002602001015183868f8d81518110613a1c57613a1c614325565b60200260200101518f8e81518110613a3657613a36614325565b60200260200101516040518663ffffffff1660e01b8152600401613a5d949392919061486a565b5f604051808303818588803b158015613a74575f80fd5b505af1158015613a86573d5f803e3d5ffd5b505050505050613b3e565b856001600160a01b03166355442b59898981518110613ab257613ab2614325565b602002602001015185858e8c81518110613ace57613ace614325565b60200260200101518e8d81518110613ae857613ae8614325565b60200260200101516040518663ffffffff1660e01b8152600401613b0f94939291906148b4565b5f604051808303818588803b158015613b26575f80fd5b505af1158015613b38573d5f803e3d5ffd5b50505050505b5050505050505b600101613542565b50505050505050565b5f805f60035f9054906101000a90046001600160a01b03166001600160a01b03166314b19c5a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613ba9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613bcd9190614497565b5f86815260066020526040812054945063ffffffff919091169150839003613c0857604051637c946ed760e01b815260040160405180910390fd5b808303613c3d5782613c1b6001836142ed565b604051637ae5968560e01b815260048101929092526024820152604401610754565b5f858152600760205260409020548015801590613c5a5750808410155b15613c6b5783613c1b6001836142ed565b613c758585614484565b92505f81118015613c8557508083115b15613c8e578092505b81831115613c9a578192505b50509250929050565b5f60208284031215613cb3575f80fd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613cf757613cf7613cba565b604052919050565b5f82601f830112613d0e575f80fd5b813567ffffffffffffffff811115613d2857613d28613cba565b613d3b601f8201601f1916602001613cce565b818152846020838601011115613d4f575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f8060808587031215613d7e575f80fd5b843593506020850135925060408501359150606085013567ffffffffffffffff811115613da9575f80fd5b613db587828801613cff565b91505092959194509250565b5f67ffffffffffffffff821115613dda57613dda613cba565b5060051b60200190565b5f82601f830112613df3575f80fd5b81356020613e08613e0383613dc1565b613cce565b8083825260208201915060208460051b870101935086841115613e29575f80fd5b602086015b84811015613e455780358352918301918301613e2e565b509695505050505050565b5f82601f830112613e5f575f80fd5b81356020613e6f613e0383613dc1565b82815260059290921b84018101918181019086841115613e8d575f80fd5b8286015b84811015613e4557803567ffffffffffffffff811115613eaf575f80fd5b613ebd8986838b0101613cff565b845250918301918301613e91565b5f805f805f60a08688031215613edf575f80fd5b8535945067ffffffffffffffff8060208801351115613efc575f80fd5b613f0c8860208901358901613de4565b94508060408801351115613f1e575f80fd5b6040870135870188601f820112613f33575f80fd5b613f40613e038235613dc1565b81358082526020808301929160051b8401018b1015613f5d575f80fd5b602083015b6020843560051b850101811015613ff7578481351115613f80575f80fd5b803584018c603f820112613f92575f80fd5b613fa2613e036020830135613dc1565b602082810135808352908201919060051b83016040018f811115613fc4575f80fd5b6040840193505b80841015613fe6578335835260209384019390920191613fcb565b508552505060209283019201613f62565b5095505050606087013581101561400c575f80fd5b61401c8860608901358901613e50565b9250806080880135111561402e575f80fd5b5061403f8760808801358801613de4565b90509295509295909350565b5f805f6060848603121561405d575f80fd5b505081359360208301359350604090920135919050565b634e487b7160e01b5f52602160045260245ffd5b60208101600483106140a857634e487b7160e01b5f52602160045260245ffd5b91905290565b5f602082840312156140be575f80fd5b8135600481106140cc575f80fd5b9392505050565b5f805f80608085870312156140e6575f80fd5b5050823594602084013594506040840135936060013592509050565b80356001600160a01b0381168114614118575f80fd5b919050565b5f6020828403121561412d575f80fd5b6140cc82614102565b5f8060408385031215614147575f80fd5b50508035926020909101359150565b5f805f60608486031215614168575f80fd5b61417184614102565b925061417f60208501614102565b915061418d60408501614102565b90509250925092565b5f80604083850312156141a7575f80fd5b823567ffffffffffffffff808211156141be575f80fd5b6141ca86838701613de4565b935060208501359150808211156141df575f80fd5b506141ec85828601613de4565b9150509250929050565b5f8060408385031215614207575f80fd5b823567ffffffffffffffff8082111561421e575f80fd5b818501915085601f830112614231575f80fd5b81356020614241613e0383613dc1565b82815260059290921b8401810191818101908984111561425f575f80fd5b948201945b838610156142845761427586614102565b82529482019490820190614264565b965050860135925050808211156141df575f80fd5b805160ff81168114614118575f80fd5b5f602082840312156142b9575f80fd5b6140cc82614299565b5f602082840312156142d2575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b81810381811115614300576143006142d9565b92915050565b5f60208284031215614316575f80fd5b815180151581146140cc575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f815180845260208085019450602084015f5b838110156143685781518752958201959082019060010161434c565b509495945050505050565b5f82825180855260208086019550808260051b8401018186015f5b848110156143e157858303601f190189528151805180855290850190858501905f5b818110156143cc578351835292870192918701916001016143b0565b5050998501999350509083019060010161438e565b5090979650505050505050565b60c081525f61440060c0830189614339565b6020838203818501528189518084528284019150828160051b850101838c015f5b8381101561444f57601f1987840301855261443d838351614339565b94860194925090850190600101614421565b50508681036040880152614463818c614373565b606088019a909a525050505060808301949094525060a00152509392505050565b80820180821115614300576143006142d9565b5f602082840312156144a7575f80fd5b815163ffffffff811681146140cc575f80fd5b80516bffffffffffffffffffffffff81168114614118575f80fd5b5f608082840312156144e5575f80fd5b6040516080810181811067ffffffffffffffff8211171561450857614508613cba565b604052614514836144ba565b8152614522602084016144ba565b6020820152604083015161ffff8116811461453b575f80fd5b604082015261454c60608401614299565b60608201529392505050565b5f8060408385031215614569575f80fd5b505080516020909101519092909150565b8082028115828204841417614300576143006142d9565b634e487b7160e01b5f52601260045260245ffd5b5f826145b3576145b3614591565b500490565b600181815b808511156145f257815f19048211156145d8576145d86142d9565b808516156145e557918102915b93841c93908002906145bd565b509250929050565b5f8261460857506001614300565b8161461457505f614300565b816001811461462a576002811461463457614650565b6001915050614300565b60ff841115614645576146456142d9565b50506001821b614300565b5060208310610133831016604e8410600b8410161715614673575081810a614300565b61467d83836145b8565b805f1904821115614690576146906142d9565b029392505050565b5f6140cc83836145fa565b6001600160a01b0384168152606060208201525f6146c46060830185614339565b82810360408401526146d68185614339565b9695505050505050565b848152836020820152608060408201525f6146fe6080830185614339565b82810360608401526147108185614339565b979650505050505050565b5f815180845260208085019450602084015f5b838110156143685781516001600160a01b03168752958201959082019060010161472e565b604081525f614765604083018561471b565b82810360208401526147778185614339565b95945050505050565b5f67ffffffffffffffff8084168061479a5761479a614591565b92169190910492915050565b67ffffffffffffffff8281168282160390808211156147c7576147c76142d9565b5092915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0385168152836020820152608060408201525f61482360808301856147ce565b905082606083015295945050505050565b848152836020820152608060408201525f61482360808301856147ce565b5f60018201614863576148636142d9565b5060010190565b608081525f61487c608083018761471b565b828103602084015261488e8187614339565b905082810360408401526148a281866147ce565b91505082606083015295945050505050565b608081525f61487c608083018761433956fea26469706673582212204f62b365dfacc16118c8e0397d13c78fb01e19f895ea8e406a87973c6c961c4c64736f6c63430008190033", + "deployedBytecode": "0x6080604052600436106101da575f3560e01c806379bc81dd116100fd578063bc7d5c5c11610092578063dcb5ccc411610062578063dcb5ccc4146105f9578063e09177781461062d578063e6be59e714610660578063f4da12ba14610693575f80fd5b8063bc7d5c5c14610568578063d529779314610587578063d7accbcc146105a6578063d8bf69bf146105da575f80fd5b80639649a35c116100cd5780639649a35c146104eb578063a5edd4fc146104ff578063a6f9dae11461051e578063bb78678f1461053d575f80fd5b806379bc81dd1461046e5780638513e77d1461048d5780638833c205146104b85780638da5cb5b146104cc575f80fd5b80633c18d1dd1161017357806361d027b31161014357806361d027b3146103d257806363096509146103f157806363c4d28e14610410578063777e49c91461042f575f80fd5b80633c18d1dd146103345780634ac7251d146103675780635a55a482146103865780635c975abb146103a5575f80fd5b80632ad923dc116101ae5780632ad923dc146102cc5780632c0f3f29146102f757806334be5af41461030c5780633907196c14610321575f80fd5b806231d115146101de5780630d17db111461022e5780630d3241ee1461026c5780632a3bb6931461028b575b5f80fd5b3480156101e9575f80fd5b506102117f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b348015610239575f80fd5b5061025c610248366004613ca3565b600a6020525f908152604090205460ff1681565b6040519015158152602001610225565b348015610277575f80fd5b50600554610211906001600160a01b031681565b348015610296575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610225565b3480156102d7575f80fd5b506102be6102e6366004613ca3565b60066020525f908152604090205481565b61030a610305366004613d6b565b6106a7565b005b348015610317575f80fd5b506102be60015481565b61030a61032f366004613ecb565b610bf4565b34801561033f575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b348015610372575f80fd5b50600354610211906001600160a01b031681565b348015610391575f80fd5b5061030a6103a036600461404b565b61114b565b3480156103b0575f80fd5b506002546103c590600160a81b900460ff1681565b6040516102259190614088565b3480156103dd575f80fd5b50600454610211906001600160a01b031681565b3480156103fc575f80fd5b5061030a61040b3660046140ae565b611315565b34801561041b575f80fd5b5061030a61042a366004613ca3565b6113d4565b34801561043a575f80fd5b5061044e6104493660046140d3565b611681565b604080519485526020850193909352918301526060820152608001610225565b348015610479575f80fd5b5061030a61048836600461404b565b611bc6565b348015610498575f80fd5b506102be6104a7366004613ca3565b60076020525f908152604090205481565b3480156104c3575f80fd5b506102be5f5481565b3480156104d7575f80fd5b50600254610211906001600160a01b031681565b3480156104f6575f80fd5b5061030a611cd5565b34801561050a575f80fd5b5061030a610519366004613ca3565b612077565b348015610529575f80fd5b5061030a61053836600461411d565b612243565b348015610548575f80fd5b506102be610557366004613ca3565b60096020525f908152604090205481565b348015610573575f80fd5b5061030a610582366004614136565b612300565b348015610592575f80fd5b5061030a6105a1366004614156565b6123b0565b3480156105b1575f80fd5b506105c56105c0366004614196565b61251e565b60408051928352602083019190915201610225565b3480156105e5575f80fd5b5061030a6105f43660046141f6565b61295b565b348015610604575f80fd5b50610211610613366004613ca3565b60086020525f90815260409020546001600160a01b031681565b348015610638575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b34801561066b575f80fd5b506102be7f000000000000000000000000000000000000000000000000000000000000000081565b34801561069e575f80fd5b506102be612abe565b6002546001600160a01b90910460ff1611156106d6576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b1790555f83900361070a57604051637c946ed760e01b815260040160405180910390fd5b5f82900361072b5760405163d92e233d60e01b815260040160405180910390fd5b5f548085111561075d57604051637ae5968560e01b815260048101869052602481018290526044015b60405180910390fd5b60028054600160a81b900460ff169081600381111561077e5761077e614074565b148061079b5750600381600381111561079957610799614074565b145b8061081257506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af11580156107e7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061080b91906142a9565b60ff166002145b15610830576040516313d0ff5960e31b815260040160405180910390fd5b5f8581526008602090815260408083205481517fa8b2ae0200000000000000000000000000000000000000000000000000000000815291516001600160a01b039091169392849263a8b2ae0292600480830193928290030181865afa15801561089b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108bf91906142c2565b90505f805f806108d18c8c8c88611681565b5f81815260066020526040902082905592965090945092509050821561094b57600354604051635e148f0960e11b8152600481018590526001600160a01b039091169063bc291e12906024015f604051808303815f87803b158015610934575f80fd5b505af1158015610946573d5f803e3d5ffd5b505050505b5f8415610b8157505f8b815260096020526040902054849080156109a5578181106109845761097a82826142ed565b90505f9150610994565b61098e81836142ed565b91505f90505b5f8d81526009602052604090208190555b8115610b72576040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610a0f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a3391906142c2565b60048054604051637ff796ab60e01b815230928101929092525f6024830152604482018690529192506001600160a01b0390911690637ff796ab906064016020604051808303815f875af1158015610a8d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ab19190614306565b506040516370a0823160e01b815230600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610b16573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3a91906142c2565b610b4491906142ed565b9050828114610b705760405163312b003360e01b81526004810182905260248101849052604401610754565b505b610b7f8d8d888e86612aea565b505b604080518d8152602081018d9052908101869052606081018290526080810185905233907f4095040bd441bb6761c0f983f93688032932a70ea67c45acf217522134d0e90c9060a00160405180910390a250506002805460ff60a01b1916600160a01b1790555050505050505050505050565b6002546001600160a01b90910460ff161115610c23576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b179055610c4284848484612ce8565b5f5480861115610c6f57604051637ae5968560e01b81526004810187905260248101829052604401610754565b60028054600160a81b900460ff1690816003811115610c9057610c90614074565b1480610cad57506003816003811115610cab57610cab614074565b145b80610d2457506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af1158015610cf9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d1d91906142a9565b60ff166002145b15610d42576040516313d0ff5960e31b815260040160405180910390fd5b6060806060610d528a8a8a612fe6565b825192955090935091505f9084906002908110610d7157610d71614325565b60200260200101511115610dfd5760035483516001600160a01b039091169063bc291e129085906002908110610da957610da9614325565b60200260200101516040518263ffffffff1660e01b8152600401610dcf91815260200190565b5f604051808303815f87803b158015610de6575f80fd5b505af1158015610df8573d5f803e3d5ffd5b505050505b5f835f81518110610e1057610e10614325565b60200260200101511115611094575f83600181518110610e3257610e32614325565b60200260200101511115611086576040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610ea4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ec891906142c2565b60045485519192506001600160a01b031690637ff796ab9030905f9088906001908110610ef757610ef7614325565b60209081029190910101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b1681526001600160a01b039093166004840152602483019190915260448201526064016020604051808303815f875af1158015610f6a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f8e9190614306565b506040516370a0823160e01b815230600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610ff3573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061101791906142c2565b61102191906142ed565b90508360018151811061103657611036614325565b6020026020010151811461108457808460018151811061105857611058614325565b602002602001015160405163312b003360e01b8152600401610754929190918252602082015260400190565b505b6110948989848a858b613540565b336001600160a01b03167f4e8f98bab2ce9f2ab5649073958662ae3277689fdf749865832601431e3153ac8a8a85875f815181106110d4576110d4614325565b6020026020010151886001815181106110ef576110ef614325565b60200260200101518960028151811061110a5761110a614325565b6020026020010151604051611124969594939291906143ee565b60405180910390a250506002805460ff60a01b1916600160a01b1790555050505050505050565b6002546001600160a01b0316331461118b5760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b821580611196575081155b8061119f575080155b156111bd57604051637c946ed760e01b815260040160405180910390fd5b4683036111e057604051633881b68960e01b815260048101849052602401610754565b5f838152600960205260408120546111f9908490614484565b90506bffffffffffffffffffffffff81111561123d57604051637ae5968560e01b8152600481018290526bffffffffffffffffffffffff6024820152604401610754565b5f8481526009602090815260408083208490556008909152908190205490517fac65ded2000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b0390911690819063ac65ded2906024015f604051808303815f87803b1580156112b4575f80fd5b505af11580156112c6573d5f803e3d5ffd5b505060408051888152602081018890529081018590528592507f2192822efd68ddf583804c65675b73a59694e672cab1758eb6714613f932a97591506060015b60405180910390a25050505050565b6002546001600160a01b031633146113555760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b600280548291907fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff16600160a81b83600381111561139557611395614074565b02179055507fa814f27828c0243d429ea8c7033cb10f0c825b9466fdc04f63e0cca26c28eb8a816040516113c99190614088565b60405180910390a150565b6005546001600160a01b031633146114145760055460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610754565b807f00000000000000000000000000000000000000000000000000000000000000000361147657604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b600354604080517f14b19c5a00000000000000000000000000000000000000000000000000000000815290515f926001600160a01b0316916314b19c5a9160048083019260209291908290030181865afa1580156114d6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114fa9190614497565b60035463ffffffff9190911691505f906001600160a01b031663d4ee9f8d6115236001856142ed565b6040518263ffffffff1660e01b815260040161154191815260200190565b602060405180830381865afa15801561155c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061158091906142c2565b90505f60035f9054906101000a90046001600160a01b03166001600160a01b031663d2b3996f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115f79190614497565b63ffffffff1690505f62093a8061160e8385614484565b61161891906142ed565b905080421061164357604051637ae5968560e01b815242600482015260248101829052604401610754565b5f858152600760205260408082208690555186917f5a6a4aed2babbf3fe4cddce74151568eaac96f250cf910532f6528b1f6ee13d891a25050505050565b5f805f80865f036116a557604051637c946ed760e01b815260040160405180910390fd5b5f8690036116c65760405163d92e233d60e01b815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000860361172857604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b5060408051808201825286815260209081018881528251808301899052905181840152825180820384018152606090910190925281519101205f61176c828a613b56565b6005546040516317d5e89d60e31b8152600481018b9052602481018c90529195509192506001600160a01b039091169063beaf44e8906044015f604051808303815f87803b1580156117bc575f80fd5b505af11580156117ce573d5f803e3d5ffd5b5083925050505b83811015611bb9575f818152600a602052604090205460ff16611bb157600354604051631ddf133560e01b8152600481018390525f916001600160a01b031690631ddf133590602401608060405180830381865afa158015611839573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061185d91906144d5565b606081015190915060ff16156118fc57604081015161ffff16158015611893575060208101516bffffffffffffffffffffffff16155b156118f75761ffff7f00000000000000000000000000000000000000000000000000000000000000001660408201526bffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660208201525b611902565b50611bb1565b60035460405163d4ee9f8d60e01b8152600481018490525f916001600160a01b03169063d4ee9f8d90602401602060405180830381865afa158015611949573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061196d91906142c2565b600554604051630c88d47f60e41b8152600481018d9052602481018e9052604481018390529192505f9182916001600160a01b03169063c88d47f0906064016040805180830381865afa1580156119c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119ea9190614558565b91509150805f03611a32575f858152600a60205260409020805460ff191660011790558351611a27906bffffffffffffffffffffffff168a614484565b985050505050611bb1565b83515f9081906bffffffffffffffffffffffff168184821115611a5f57611a5985836142ed565b90508491505b6040880151611a789061ffff16655af3107a400061457a565b861015611aae57670de0b6b3a764000086611a938484614484565b611a9d919061457a565b611aa791906145a5565b9250611b9c565b670de0b6b3a7640000611ac1878461457a565b611acb91906145a5565b9350670de0b6b3a7640000611ae0878361457a565b611aea91906145a5565b925087602001516bffffffffffffffffffffffff16915081841115611b2357611b1382856142ed565b611b1d9084614484565b92508193505b60128f1015611b8f575f8f6012611b3a91906142ed565b611b4590600a614698565b611b4f90866145a5565b90508f6012611b5e91906142ed565b611b6990600a614698565b611b73908261457a565b9050611b7f81866142ed565b611b899085614484565b90945092505b611b99848f614484565b9d505b611ba6838e614484565b9c5050505050505050505b6001016117d5565b5050945094509450949050565b5f838152600860205260409020546001600160a01b0316338114611c27576040517fdeeeedec0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0382166024820152604401610754565b5f84815260096020526040812054611c40908590614484565b90506bffffffffffffffffffffffff811115611c8457604051637ae5968560e01b8152600481018290526bffffffffffffffffffffffff6024820152604401610754565b5f85815260096020908152604091829020839055815187815290810186905290810182905283907f2192822efd68ddf583804c65675b73a59694e672cab1758eb6714613f932a97590606001611306565b6002546001600160a01b90910460ff161115611d04576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b1790555f80548190611d47907f000000000000000000000000000000000000000000000000000000000000000090613b56565b6005546040516317d5e89d60e31b81527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201529294509092506001600160a01b03169063beaf44e8906044015f604051808303815f87803b158015611db3575f80fd5b505af1158015611dc5573d5f803e3d5ffd5b50507f00000000000000000000000000000000000000000000000000000000000000005f90815260066020526040812084905591508390505b82811015611fb557600354604051631ddf133560e01b8152600481018390525f916001600160a01b031690631ddf133590602401608060405180830381865afa158015611e4d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e7191906144d5565b60035460405163d4ee9f8d60e01b8152600481018590529192505f916001600160a01b039091169063d4ee9f8d90602401602060405180830381865afa158015611ebd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ee191906142c2565b600554604051630c88d47f60e41b81527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604481018390529192505f916001600160a01b039091169063c88d47f0906064016040805180830381865afa158015611f58573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f7c9190614558565b508351909150611f9b9082906bffffffffffffffffffffffff1661457a565b611fa59086614484565b9450505050806001019050611dfe565b50611fc8670de0b6b3a7640000826145a5565b9050801561202a57600354604051635e148f0960e11b8152600481018390526001600160a01b039091169063bc291e12906024015f604051808303815f87803b158015612013575f80fd5b505af1158015612025573d5f803e3d5ffd5b505050505b60405181815233907f2a8de497d698d6869cb0844411788378e76214d03a541eec6ba514b795d9f42e9060200160405180910390a250506002805460ff60a01b1916600160a01b17905550565b6005546001600160a01b031633146120b75760055460405163312d21ff60e11b81523360048201526001600160a01b039091166024820152604401610754565b60028054600160a81b900460ff16908160038111156120d8576120d8614074565b14806120f5575060038160038111156120f3576120f3614074565b145b8061216c57506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af1158015612141573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061216591906142a9565b60ff166002145b1561218a576040516313d0ff5960e31b815260040160405180910390fd5b60035f9054906101000a90046001600160a01b03166001600160a01b03166314b19c5a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121da573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121fe9190614497565b5f8381526006602052604080822063ffffffff93909316909255905183917f5381b67b592d2dc84b61238222ab88ee04db3b3a082894a445c4e5cfa8ba11be91a25050565b6002546001600160a01b031633146122835760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b6001600160a01b0381166122aa5760405163d92e233d60e01b815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f4ffd725fc4a22075e9ec71c59edf9c38cdeb588a91b24fc5b61388c5be41282b905f90a250565b6002546001600160a01b031633146123405760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b81158061234b575080155b1561236957604051637c946ed760e01b815260040160405180910390fd5b5f829055600181905560408051838152602081018390527f61f6c4cc9665a257352c0b46189ffc2ae6fbbc11e155ff20901217ff203a517e91015b60405180910390a15050565b6002546001600160a01b031633146123f05760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b6001600160a01b03831615612453576003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0385169081179091556040517f4672fe7e13cfb163442d0b729b5733fb3efafc66cbe3677eac9940eb41c284c2905f90a25b6001600160a01b038216156124b6576004805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384169081179091556040517f7dae230f18360d76a040c81f050aa14eb9d6dc7901b20fc5d855e2a20fe814d1905f90a25b6001600160a01b03811615612519576005805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040517f04a606379838ed6fc83fd189eea9d1835b5eff05035c4b74622911ea2ae6b217905f90a25b505050565b5f806001600260149054906101000a900460ff1660ff161115612554576040516345f5ce8b60e11b815260040160405180910390fd5b6002805460ff60a01b1916600160a11b179081905560ff600160a81b90910416600181600381111561258857612588614074565b14806125a5575060038160038111156125a3576125a3614074565b145b8061261c57506004805460408051635c975abb60e01b815290516001600160a01b0390921692635c975abb92828201926020929082900301815f875af11580156125f1573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061261591906142a9565b60ff166002145b1561263a576040516313d0ff5960e31b815260040160405180910390fd5b6003546040517f2e070f540000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690632e070f5490612687903390899089906004016146a3565b60408051808303815f875af11580156126a2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126c69190614558565b90935091505f806126d78486614484565b11156128af575f831561276d576040516370a0823160e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612746573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061276a91906142c2565b90505b60048054604051637ff796ab60e01b8152339281019290925260248201879052604482018690526001600160a01b031690637ff796ab906064016020604051808303815f875af11580156127c3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127e79190614306565b915083156128ad576040516370a0823160e01b815233600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015612853573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061287791906142c2565b61288191906142ed565b90508381146128ad5760405163312b003360e01b81526004810182905260248101859052604401610754565b505b806128f6576040517f942dc9da0000000000000000000000000000000000000000000000000000000081523360048201526024810185905260448101849052606401610754565b336001600160a01b03167fbe9ae4aaa6e41ee5c966cad91e78ec7202d0062fe8c9564b28629a614003cf828585898960405161293594939291906146e0565b60405180910390a250506002805460ff60a01b1916600160a01b17905590939092509050565b6002546001600160a01b0316331461299b5760025460405163521eb56d60e11b81523360048201526001600160a01b039091166024820152604401610754565b815115806129ab57508051825114155b156129d657815181516040516308151c1160e41b815260048101929092526024820152604401610754565b5f5b8151811015612a8c578181815181106129f3576129f3614325565b60200260200101515f03612a1a57604051637c946ed760e01b815260040160405180910390fd5b828181518110612a2c57612a2c614325565b602002602001015160085f848481518110612a4957612a49614325565b602002602001015181526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508060010190506129d8565b507fe87460f6c400fa0166984512586d7bdf03a3230bbadf9651f27f08716dd77fa582826040516123a4929190614753565b6024612ad3600267ffffffffffffffff614780565b612add91906147a6565b67ffffffffffffffff1681565b5f858152600860205260409020546001600160a01b03168115612bb2576040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b038281166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303815f875af1158015612b8c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bb09190614306565b505b6024612bc7600267ffffffffffffffff614780565b612bd191906147a6565b67ffffffffffffffff168611612c64576040517fb2267a7b00000000000000000000000000000000000000000000000000000000815285906001600160a01b0383169063b2267a7b903490612c309085908a908a908a906004016147fc565b5f604051808303818588803b158015612c47575f80fd5b505af1158015612c59573d5f803e3d5ffd5b505050505050612ce0565b6040517f6585ecdc0000000000000000000000000000000000000000000000000000000081526001600160a01b03821690636585ecdc903490612cb1908990899089908990600401614834565b5f604051808303818588803b158015612cc8575f80fd5b505af1158015612cda573d5f803e3d5ffd5b50505050505b505050505050565b8251845114612d1757835183516040516308151c1160e41b815260048101929092526024820152604401610754565b8151845114612d4657835182516040516308151c1160e41b815260048101929092526024820152604401610754565b8051845114612d7557835181516040516308151c1160e41b815260048101929092526024820152604401610754565b5f805f5b8651811015612fbc57868181518110612d9457612d94614325565b60200260200101518310612dd857868181518110612db457612db4614325565b6020026020010151604051633881b68960e01b815260040161075491815260200190565b868181518110612dea57612dea614325565b60200260200101519250858181518110612e0657612e06614325565b6020026020010151515f03612e2e57604051637c946ed760e01b815260040160405180910390fd5b838181518110612e4057612e40614325565b602002602001015182612e539190614484565b91505f600154905080878381518110612e6e57612e6e614325565b6020026020010151511115612ebd57868281518110612e8f57612e8f614325565b60200260200101515181604051637ae5968560e01b8152600401610754929190918252602082015260400190565b5f805b888481518110612ed257612ed2614325565b602002602001015151811015612fae57888481518110612ef457612ef4614325565b60200260200101518181518110612f0d57612f0d614325565b60200260200101515f1c825f1c10612f6e57888481518110612f3157612f31614325565b60200260200101518181518110612f4a57612f4a614325565b6020026020010151604051636aba776560e11b815260040161075491815260200190565b888481518110612f8057612f80614325565b60200260200101518181518110612f9957612f99614325565b60200260200101519150806001019050612ec0565b505050806001019050612d79565b50803414612ce05760405163312b003360e01b815234600482015260248101829052604401610754565b6040805160038082526080820190925260609182918291602082018380368337019050509250845167ffffffffffffffff81111561302657613026613cba565b60405190808252806020026020018201604052801561305957816020015b60608152602001906001900390816130445790505b509150845167ffffffffffffffff81111561307657613076613cba565b60405190808252806020026020018201604052801561309f578160200160208202803683370190505b5090505f5b8551811015613536575f60085f8884815181106130c3576130c3614325565b602002602001015181526020019081526020015f205f9054906101000a90046001600160a01b031690505f816001600160a01b031663a8b2ae026040518163ffffffff1660e01b8152600401602060405180830381865afa15801561312a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061314e91906142c2565b905086838151811061316257613162614325565b60200260200101515167ffffffffffffffff81111561318357613183613cba565b6040519080825280602002602001820160405280156131ac578160200160208202803683370190505b508584815181106131bf576131bf614325565b60200260200101819052505f5b8784815181106131de576131de614325565b6020026020010151518110156133c5577f000000000000000000000000000000000000000000000000000000000000000088858151811061322157613221614325565b6020026020010151828151811061323a5761323a614325565b60200260200101510361328257604051636aba776560e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152602401610754565b5f805f806132dd8e8e8a8151811061329c5761329c614325565b60200260200101518e8b815181106132b6576132b6614325565b602002602001015188815181106132cf576132cf614325565b602002602001015189611681565b5f8181526006602052604090208290558d519397509195509350915084908b908a90811061330d5761330d614325565b6020026020010151868151811061332657613326614325565b6020026020010181815250508389898151811061334557613345614325565b602002602001018181516133599190614484565b9052508a5184908c905f9061337057613370614325565b602002602001018181516133849190614484565b9052508a5183908c90600290811061339e5761339e614325565b602002602001018181516133b29190614484565b90525050600190930192506131cc915050565b505f8484815181106133d9576133d9614325565b602002602001015111156134e8575f60095f8a86815181106133fd576133fd614325565b602002602001015181526020019081526020015f205490505f8111156134e65784848151811061342f5761342f614325565b602002602001015181106134885784848151811061344f5761344f614325565b60200260200101518161346291906142ed565b90505f85858151811061347757613477614325565b6020026020010181815250506134b6565b8085858151811061349b5761349b614325565b602002602001018181516134af91906142ed565b9052505f90505b8060095f8b87815181106134cc576134cc614325565b602002602001015181526020019081526020015f20819055505b505b8383815181106134fa576134fa614325565b60200260200101518660018151811061351557613515614325565b602002602001018181516135299190614484565b90525050506001016130a4565b5093509350939050565b5f5b8651811015613b4d575f60085f89848151811061356157613561614325565b602002602001015181526020019081526020015f205f9054906101000a90046001600160a01b031690505f84838151811061359e5761359e614325565b60200260200101511115613669577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb828685815181106135ee576135ee614325565b60200260200101516040518363ffffffff1660e01b81526004016136279291906001600160a01b03929092168252602082015260400190565b6020604051808303815f875af1158015613643573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136679190614306565b505b5f8088848151811061367d5761367d614325565b60200260200101515167ffffffffffffffff81111561369e5761369e613cba565b6040519080825280602002602001820160405280156136c7578160200160208202803683370190505b5090505f5b8985815181106136de576136de614325565b602002602001015151811015613760575f89868151811061370157613701614325565b6020026020010151828151811061371a5761371a614325565b6020026020010151111561375857600182828151811061373c5761373c614325565b9115156020928302919091019091015261375583614852565b92505b6001016136cc565b50815f0361377057505050613b45565b5f8267ffffffffffffffff81111561378a5761378a613cba565b6040519080825280602002602001820160405280156137b3578160200160208202803683370190505b5090505f8367ffffffffffffffff8111156137d0576137d0613cba565b6040519080825280602002602001820160405280156137f9578160200160208202803683370190505b5090505f805b8c888151811061381157613811614325565b6020026020010151518110156138f55784818151811061383357613833614325565b6020026020010151156138ed578c888151811061385257613852614325565b6020026020010151818151811061386b5761386b614325565b602002602001015184838151811061388557613885614325565b6020026020010181815250508b88815181106138a3576138a3614325565b602002602001015181815181106138bc576138bc614325565b60200260200101518383815181106138d6576138d6614325565b60209081029190910101526138ea82614852565b91505b6001016137ff565b50602461390b600267ffffffffffffffff614780565b61391591906147a6565b67ffffffffffffffff168d888151811061393157613931614325565b602002602001015111613a91575f835167ffffffffffffffff81111561395957613959613cba565b604051908082528060200260200182016040528015613982578160200160208202803683370190505b5090505f5b84518110156139de578481815181106139a2576139a2614325565b60200260200101515f1c8282815181106139be576139be614325565b6001600160a01b0390921660209283029190910190910152600101613987565b50866001600160a01b031663bde526618a8a81518110613a0057613a00614325565b602002602001015183868f8d81518110613a1c57613a1c614325565b60200260200101518f8e81518110613a3657613a36614325565b60200260200101516040518663ffffffff1660e01b8152600401613a5d949392919061486a565b5f604051808303818588803b158015613a74575f80fd5b505af1158015613a86573d5f803e3d5ffd5b505050505050613b3e565b856001600160a01b03166355442b59898981518110613ab257613ab2614325565b602002602001015185858e8c81518110613ace57613ace614325565b60200260200101518e8d81518110613ae857613ae8614325565b60200260200101516040518663ffffffff1660e01b8152600401613b0f94939291906148b4565b5f604051808303818588803b158015613b26575f80fd5b505af1158015613b38573d5f803e3d5ffd5b50505050505b5050505050505b600101613542565b50505050505050565b5f805f60035f9054906101000a90046001600160a01b03166001600160a01b03166314b19c5a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613ba9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613bcd9190614497565b5f86815260066020526040812054945063ffffffff919091169150839003613c0857604051637c946ed760e01b815260040160405180910390fd5b808303613c3d5782613c1b6001836142ed565b604051637ae5968560e01b815260048101929092526024820152604401610754565b5f858152600760205260409020548015801590613c5a5750808410155b15613c6b5783613c1b6001836142ed565b613c758585614484565b92505f81118015613c8557508083115b15613c8e578092505b81831115613c9a578192505b50509250929050565b5f60208284031215613cb3575f80fd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613cf757613cf7613cba565b604052919050565b5f82601f830112613d0e575f80fd5b813567ffffffffffffffff811115613d2857613d28613cba565b613d3b601f8201601f1916602001613cce565b818152846020838601011115613d4f575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f8060808587031215613d7e575f80fd5b843593506020850135925060408501359150606085013567ffffffffffffffff811115613da9575f80fd5b613db587828801613cff565b91505092959194509250565b5f67ffffffffffffffff821115613dda57613dda613cba565b5060051b60200190565b5f82601f830112613df3575f80fd5b81356020613e08613e0383613dc1565b613cce565b8083825260208201915060208460051b870101935086841115613e29575f80fd5b602086015b84811015613e455780358352918301918301613e2e565b509695505050505050565b5f82601f830112613e5f575f80fd5b81356020613e6f613e0383613dc1565b82815260059290921b84018101918181019086841115613e8d575f80fd5b8286015b84811015613e4557803567ffffffffffffffff811115613eaf575f80fd5b613ebd8986838b0101613cff565b845250918301918301613e91565b5f805f805f60a08688031215613edf575f80fd5b8535945067ffffffffffffffff8060208801351115613efc575f80fd5b613f0c8860208901358901613de4565b94508060408801351115613f1e575f80fd5b6040870135870188601f820112613f33575f80fd5b613f40613e038235613dc1565b81358082526020808301929160051b8401018b1015613f5d575f80fd5b602083015b6020843560051b850101811015613ff7578481351115613f80575f80fd5b803584018c603f820112613f92575f80fd5b613fa2613e036020830135613dc1565b602082810135808352908201919060051b83016040018f811115613fc4575f80fd5b6040840193505b80841015613fe6578335835260209384019390920191613fcb565b508552505060209283019201613f62565b5095505050606087013581101561400c575f80fd5b61401c8860608901358901613e50565b9250806080880135111561402e575f80fd5b5061403f8760808801358801613de4565b90509295509295909350565b5f805f6060848603121561405d575f80fd5b505081359360208301359350604090920135919050565b634e487b7160e01b5f52602160045260245ffd5b60208101600483106140a857634e487b7160e01b5f52602160045260245ffd5b91905290565b5f602082840312156140be575f80fd5b8135600481106140cc575f80fd5b9392505050565b5f805f80608085870312156140e6575f80fd5b5050823594602084013594506040840135936060013592509050565b80356001600160a01b0381168114614118575f80fd5b919050565b5f6020828403121561412d575f80fd5b6140cc82614102565b5f8060408385031215614147575f80fd5b50508035926020909101359150565b5f805f60608486031215614168575f80fd5b61417184614102565b925061417f60208501614102565b915061418d60408501614102565b90509250925092565b5f80604083850312156141a7575f80fd5b823567ffffffffffffffff808211156141be575f80fd5b6141ca86838701613de4565b935060208501359150808211156141df575f80fd5b506141ec85828601613de4565b9150509250929050565b5f8060408385031215614207575f80fd5b823567ffffffffffffffff8082111561421e575f80fd5b818501915085601f830112614231575f80fd5b81356020614241613e0383613dc1565b82815260059290921b8401810191818101908984111561425f575f80fd5b948201945b838610156142845761427586614102565b82529482019490820190614264565b965050860135925050808211156141df575f80fd5b805160ff81168114614118575f80fd5b5f602082840312156142b9575f80fd5b6140cc82614299565b5f602082840312156142d2575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b81810381811115614300576143006142d9565b92915050565b5f60208284031215614316575f80fd5b815180151581146140cc575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f815180845260208085019450602084015f5b838110156143685781518752958201959082019060010161434c565b509495945050505050565b5f82825180855260208086019550808260051b8401018186015f5b848110156143e157858303601f190189528151805180855290850190858501905f5b818110156143cc578351835292870192918701916001016143b0565b5050998501999350509083019060010161438e565b5090979650505050505050565b60c081525f61440060c0830189614339565b6020838203818501528189518084528284019150828160051b850101838c015f5b8381101561444f57601f1987840301855261443d838351614339565b94860194925090850190600101614421565b50508681036040880152614463818c614373565b606088019a909a525050505060808301949094525060a00152509392505050565b80820180821115614300576143006142d9565b5f602082840312156144a7575f80fd5b815163ffffffff811681146140cc575f80fd5b80516bffffffffffffffffffffffff81168114614118575f80fd5b5f608082840312156144e5575f80fd5b6040516080810181811067ffffffffffffffff8211171561450857614508613cba565b604052614514836144ba565b8152614522602084016144ba565b6020820152604083015161ffff8116811461453b575f80fd5b604082015261454c60608401614299565b60608201529392505050565b5f8060408385031215614569575f80fd5b505080516020909101519092909150565b8082028115828204841417614300576143006142d9565b634e487b7160e01b5f52601260045260245ffd5b5f826145b3576145b3614591565b500490565b600181815b808511156145f257815f19048211156145d8576145d86142d9565b808516156145e557918102915b93841c93908002906145bd565b509250929050565b5f8261460857506001614300565b8161461457505f614300565b816001811461462a576002811461463457614650565b6001915050614300565b60ff841115614645576146456142d9565b50506001821b614300565b5060208310610133831016604e8410600b8410161715614673575081810a614300565b61467d83836145b8565b805f1904821115614690576146906142d9565b029392505050565b5f6140cc83836145fa565b6001600160a01b0384168152606060208201525f6146c46060830185614339565b82810360408401526146d68185614339565b9695505050505050565b848152836020820152608060408201525f6146fe6080830185614339565b82810360608401526147108185614339565b979650505050505050565b5f815180845260208085019450602084015f5b838110156143685781516001600160a01b03168752958201959082019060010161472e565b604081525f614765604083018561471b565b82810360208401526147778185614339565b95945050505050565b5f67ffffffffffffffff8084168061479a5761479a614591565b92169190910492915050565b67ffffffffffffffff8281168282160390808211156147c7576147c76142d9565b5092915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0385168152836020820152608060408201525f61482360808301856147ce565b905082606083015295945050505050565b848152836020820152608060408201525f61482360808301856147ce565b5f60018201614863576148636142d9565b5060010190565b608081525f61487c608083018761471b565b828103602084015261488e8187614339565b905082810360408401526148a281866147ce565b91505082606083015295945050505050565b608081525f61487c608083018761433956fea26469706673582212204f62b365dfacc16118c8e0397d13c78fb01e19f895ea8e406a87973c6c961c4c64736f6c63430008190033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/audits/README.md b/audits/README.md index d7dce10b..85dc3e82 100644 --- a/audits/README.md +++ b/audits/README.md @@ -10,5 +10,9 @@ An internal audit with a focus on depository implementation v.1.0.1 is located i An internal audit with a focus on PoAA Staking is located in this folder: [internal audit 4](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/internal4). +An internal audit with a focus on PoAA Staking fixing after C4A is located in this folder: [internal audit 5](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/internal5). + +An internal audit with a focus on AIP-1 (bonding) is located in this folder: [internal audit 6](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/internal6). + ### External audit Audit reports: [v1](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/Autonolas%20Tokenomics%20Smart%20Contract%20Audit.pdf) and [v2](https://sourcehat.com/audits/AutonolasTokenomics/). diff --git a/audits/internal5/README.md b/audits/internal5/README.md new file mode 100644 index 00000000..b9cafd51 --- /dev/null +++ b/audits/internal5/README.md @@ -0,0 +1,130 @@ +# Internal audit of autonolas-tokenomics +The review has been performed based on the contract code in the following repository:
+`https://github.com/valory-xyz/autonolas-tokenomics`
+commit: `357539f11e3386c18bc9370d4cd20066c7fc0599` or `tag: v1.2.2-pre-internal-audit`
+ +## Objectives +The audit focused on fixing contracts related to PoAA Staking after C4A. + +### Coverage +Hardhat coverage has been performed before the audit and can be found here: +```sh +---------------------------------|----------|----------|----------|----------|----------------| +File | % Stmts | % Branch | % Funcs | % Lines |Uncovered Lines | +---------------------------------|----------|----------|----------|----------|----------------| + contracts/ | 99.64 | 96.79 | 100 | 98.09 | | + + Dispenser.sol | 98.94 | 90.65 | 100 | 93.86 |... 0,1188,1246 | + + contracts/staking/ | 97.52 | 90.83 | 98.36 | 93.97 | | + ArbitrumDepositProcessorL1.sol | 100 | 96.15 | 100 | 97.14 | 157 | + ArbitrumTargetDispenserL2.sol | 100 | 100 | 100 | 100 | | + DefaultDepositProcessorL1.sol | 100 | 90.63 | 100 | 94.83 | 134,227,235 | + DefaultTargetDispenserL2.sol | 97.5 | 87.8 | 100 | 92.52 |... 459,489,511 | + EthereumDepositProcessor.sol | 85.71 | 88.89 | 100 | 86.11 |... 109,112,114 | + GnosisDepositProcessorL1.sol | 100 | 100 | 100 | 100 | | + GnosisTargetDispenserL2.sol | 100 | 100 | 100 | 100 | | + OptimismDepositProcessorL1.sol | 100 | 100 | 100 | 100 | | + OptimismTargetDispenserL2.sol | 100 | 100 | 100 | 100 | | + PolygonDepositProcessorL1.sol | 91.67 | 80 | 80 | 84.21 | 97,105,110 | + PolygonTargetDispenserL2.sol | 100 | 50 | 100 | 81.82 | 68,73 | + WormholeDepositProcessorL1.sol | 100 | 100 | 100 | 100 | | + WormholeTargetDispenserL2.sol | 100 | 91.67 | 100 | 96.77 | 114 | + +---------------------------------|----------|----------|----------|----------|----------------| +``` +Please, pay attention.
+[x] Noted. Missing 100% is not an obvious problem. + +#### Checking the corrections made after C4A +##### Bridging +67. Withheld tokens could become unsynchronized by using retry-ability of bridging protocols #67 +https://github.com/code-423n4/2024-05-olas-findings/issues/67 +[x] fixed + +54. OptimismTargetDispenserL2:syncWithheldTokens is callable with no sanity check on payloads and can lead to permanent loss of withheld token amounts #54 +https://github.com/code-423n4/2024-05-olas-findings/issues/54 +20. Users will lose all ETH sent as cost parameter in transactions to and from Optimism #20 +https://github.com/code-423n4/2024-05-olas-findings/issues/20 +4. The msg.value - cost for multiple cross-chain bridges are not refunded to users #4 +https://github.com/code-423n4/2024-05-olas-findings/issues/4 +[x] fixed + +32. Refunds for unconsumed gas will be lost due to incorrect refund chain ID #32 +https://github.com/code-423n4/2024-05-olas-findings/issues/32 +[x] fixed + +29. Attacker can cancel claimed staking incentives on Arbitrum #29 +https://github.com/code-423n4/2024-05-olas-findings/issues/29 +[x] fixed + +26. Non-normalized amounts sent via Wormhole lead to failure to redeem incentives #26 +https://github.com/code-423n4/2024-05-olas-findings/issues/26 +[x] fixed + +22. Arbitrary tokens and data can be bridged to GnosisTargetDispenserL2 to manipulate staking incentives #22 +https://github.com/code-423n4/2024-05-olas-findings/issues/22 +[x] fixed + +5. The refundAccount is erroneously set to msg.sender instead of tx.origin when refundAccount specified as address(0) #5 +https://github.com/code-423n4/2024-05-olas-findings/issues/5 +[x] fixed + +##### Dispenser +61. Loss of incentives if total weight in an epoch is zero #61 +https://github.com/code-423n4/2024-05-olas-findings/issues/61 +[x] fixed + +56. In retain function checkpoint nominee function is not called which can cause zero amount of tokens being retained. #56 +https://github.com/code-423n4/2024-05-olas-findings/issues/56 +[x] fixed + +38. Removed nominee doesn't receive staking incentives for the epoch in which they were removed which is against the intended behaviour #38 +https://github.com/code-423n4/2024-05-olas-findings/issues/38 +[x] fixed + +27. Unauthorized claiming of staking incentives for retainer #27 +https://github.com/code-423n4/2024-05-olas-findings/issues/27 +[x] fixed + +##### No need to change the code, just add information to the documentation +59. Changing VoteWeighting contract can result in lost staking incentives #59 +https://github.com/code-423n4/2024-05-olas-findings/issues/59 +[x] fixed + +#### Low issue +107. QA Report #107 +https://github.com/code-423n4/2024-05-olas-findings/issues/107 +``` +[N-44] Missing event for critical changes addNomenee in Dispenser +``` +[x] fixed + +110. QA Report #110 +https://github.com/code-423n4/2024-05-olas-findings/issues/110 +``` +[NonCritical-9] Missing events in sensitive function setL2TargetDispenser(address l2Dispenser) +``` +[x] fixed + +113. QA Report #113 +https://github.com/code-423n4/2024-05-olas-findings/issues/113 +``` +[L-08] Use abi.encodeCall() instead of abi.encodeWithSignature()/abi.encodeWithSelector() +grep -r encodeWithSelec ./contracts/ +./contracts/staking/OptimismDepositProcessorL1.sol: bytes memory data = abi.encodeWithSelector(RECEIVE_MESSAGE, abi.encode(targets, stakingIncentives, batchHash)); +./contracts/staking/OptimismTargetDispenserL2.sol: bytes memory data = abi.encodeWithSelector(RECEIVE_MESSAGE, abi.encode(amount, batchHash)); +./contracts/staking/ArbitrumTargetDispenserL2.sol: bytes memory data = abi.encodeWithSelector(RECEIVE_MESSAGE, abi.encode(amount, batchHash)); +./contracts/staking/GnosisTargetDispenserL2.sol: bytes memory data = abi.encodeWithSelector(RECEIVE_MESSAGE, abi.encode(amount, batchHash)); +./contracts/staking/ArbitrumDepositProcessorL1.sol: bytes memory data = abi.encodeWithSelector(RECEIVE_MESSAGE, abi.encode(targets, stakingIncentives, batchHash)); +./contracts/staking/GnosisDepositProcessorL1.sol: bytes memory data = abi.encodeWithSelector(RECEIVE_MESSAGE, abi.encode(targets, stakingIncentives, batchHash)); +``` +[x] Noted. The fact that codebase hasn't been changed is not a problem. + +### Catch up on changes. 15.07.24 +https://github.com/valory-xyz/autonolas-tokenomics/compare/v1.2.2-pre-internal-audit...v1.2.2-pre-audit
+The changes to the codebase appear to be correct. + + + + diff --git a/audits/internal6/README.md b/audits/internal6/README.md new file mode 100644 index 00000000..db892c93 --- /dev/null +++ b/audits/internal6/README.md @@ -0,0 +1,100 @@ +# Internal audit of autonolas-tokenomics +The review has been performed based on the contract code in the following repository:
+`https://github.com/valory-xyz/autonolas-tokenomics`
+commit: `12101b49a2dcdc7a7378f416ddb1611e10459b67` or `tag: v1.3.0-pre-internal-audit`
+ +## Objectives +The audit focused on contracts related to AIP-1 implementation (Bonding) in this repo. + +### Flatten version +Flatten version of contracts. [contracts](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/internal5/analysis/contracts) + +### Coverage: N/A +In this commit, the tests are in the process of being reworked and therefore the coverage section does not make sense. + +### Storage and proxy +Using sol2uml tools: https://github.com/naddison36/sol2uml
+``` +npm link sol2uml --only=production +sol2uml storage contracts/ -f png -c Tokenomics -o audits/internal4/analysis/storage +Generated png file audits/internal5/analysis/storage/Tokenomics.png +``` +[Tokenomics-storage](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/internal5/analysis/storage/Tokenomics.png)
+current deployed:
+[Tokenomics-storage-current](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/internal4/analysis/storage/Tokenomics.png)
+The new slot allocation for Tokenomics (critical as proxy pattern) does not affect the previous one. + +### Security issues. +#### Problems found instrumentally +Several checks are obtained automatically. They are commented. Some issues found need to be fixed.
+All automatic warnings are listed in the following file, concerns of which we address in more detail below:
+[slither-full](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/internal5/analysis/slither_full.txt)
+ +#### Issue +1. minOLASLeftoverAmount never setupped/updated +``` + // Minimum amount of supply such that any value below is given to the bonding account in order to close the product + uint256 public minOLASLeftoverAmount; +``` +[x] fixed + +2. Reentrancy after ERC721 "safe" mint in deposit +``` + External calls: + - _safeMint(msg.sender,bondId) (Depository-flatten.sol#891) + - require(bool,string)(ERC721TokenReceiver(to).onERC721Received(msg.sender,address(0),id,) == ERC721TokenReceiver.onERC721Received.selector,UNSAFE_RECIPIENT) (Depository-flatten.sol#461-465) + After adding _safeMint(msg.sender, bondId), it became clearly susceptible reentrancy attack. + We need to add explicit protection against reentrancy. +``` +[x] fixed + +#### General notes: more tests need to be done, needed re-audit later +``` +trackServiceDonations requires a large number of tests and coverage of all scenarios. +``` +[x] noted + +#### Notes for discussion: epsilonRate +``` +in this implementation epsilonRate is deprecated and simply not used. perhaps it makes sense (?) to use this dimensionless coefficient as a limiter. +// The IDF depends on the epsilonRate value, idf = 1 + epsilonRate, and epsilonRate is bound by 17 with 18 decimals +new +// IDF = 1 + normalized booster +idf = 1e18 + discountBooster; +maybe idf = min(1e18 + discountBooster, 1e18 + epsilonRate) +Moreover, according to calculations discountBooster <= 1e18 << max(epsilonRate) +``` +[x] IDF is never bigger than 2e18 by design + +### Re-audit 02.08.24 +The review has been performed based on the contract code in the following repository:
+`https://github.com/valory-xyz/autonolas-tokenomics`
+commit: `c76a04a64fd450e1a7a34873ea49b6a4b4b0b856` or `tag: v1.3.0-internal-audit2`
+ +### Coverage +``` +---------------------------------|----------|----------|----------|----------|----------------| +File | % Stmts | % Branch | % Funcs | % Lines |Uncovered Lines | +---------------------------------|----------|----------|----------|----------|----------------| + contracts/ | 98.83 | 96.45 | 95.51 | 97.79 | | + BondCalculator.sol | 97.44 | 98 | 85.71 | 97.22 | 181,299 | + Depository.sol | 95.56 | 92.71 | 81.25 | 93.49 |... 605,608,615 | + Dispenser.sol | 98.95 | 93.06 | 100 | 96.24 |... 0,1209,1267 | +---------------------------------|----------|----------|----------|----------|----------------| +``` +Please, pay attention. + +### Storage and proxy +Using sol2uml tools: https://github.com/naddison36/sol2uml
+``` +npm link sol2uml --only=production +sol2uml storage contracts/ -f png -c Tokenomics -o audits/internal6/analysis/storage +Generated png file audits/internal6/analysis/storage/Tokenomics.png +``` +[Tokenomics-storage](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/internal6/analysis/storage/Tokenomics.png)
+current deployed:
+[Tokenomics-storage-current](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/audits/internal4/analysis/storage/Tokenomics.png)
+The new slot allocation for Tokenomics (critical as proxy pattern) does not affect the previous one. + +### Issue +I don't see any problems. diff --git a/audits/internal6/analysis/contracts/BondCalculator-flatten.sol b/audits/internal6/analysis/contracts/BondCalculator-flatten.sol new file mode 100644 index 00000000..aebce773 --- /dev/null +++ b/audits/internal6/analysis/contracts/BondCalculator-flatten.sol @@ -0,0 +1,997 @@ +// Sources flattened with hardhat v2.22.4 https://hardhat.org +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +// Common.sol +// +// Common mathematical functions used in both SD59x18 and UD60x18. Note that these global functions do not +// always operate with SD59x18 and UD60x18 numbers. + +/*////////////////////////////////////////////////////////////////////////// + CUSTOM ERRORS +//////////////////////////////////////////////////////////////////////////*/ + +/// @notice Thrown when the resultant value in {mulDiv} overflows uint256. +error PRBMath_MulDiv_Overflow(uint256 x, uint256 y, uint256 denominator); + +/// @notice Thrown when the resultant value in {mulDiv18} overflows uint256. +error PRBMath_MulDiv18_Overflow(uint256 x, uint256 y); + +/// @notice Thrown when one of the inputs passed to {mulDivSigned} is `type(int256).min`. +error PRBMath_MulDivSigned_InputTooSmall(); + +/// @notice Thrown when the resultant value in {mulDivSigned} overflows int256. +error PRBMath_MulDivSigned_Overflow(int256 x, int256 y); + +/*////////////////////////////////////////////////////////////////////////// + CONSTANTS +//////////////////////////////////////////////////////////////////////////*/ + +/// @dev The maximum value a uint128 number can have. +uint128 constant MAX_UINT128 = type(uint128).max; + +/// @dev The maximum value a uint40 number can have. +uint40 constant MAX_UINT40 = type(uint40).max; + +/// @dev The unit number, which the decimal precision of the fixed-point types. +uint256 constant UNIT = 1e18; + +/// @dev The unit number inverted mod 2^256. +uint256 constant UNIT_INVERSE = 78156646155174841979727994598816262306175212592076161876661_508869554232690281; + +/// @dev The the largest power of two that divides the decimal value of `UNIT`. The logarithm of this value is the least significant +/// bit in the binary representation of `UNIT`. +uint256 constant UNIT_LPOTD = 262144; + +/*////////////////////////////////////////////////////////////////////////// + FUNCTIONS +//////////////////////////////////////////////////////////////////////////*/ + +/// @notice Calculates the binary exponent of x using the binary fraction method. +/// @dev Has to use 192.64-bit fixed-point numbers. See https://ethereum.stackexchange.com/a/96594/24693. +/// @param x The exponent as an unsigned 192.64-bit fixed-point number. +/// @return result The result as an unsigned 60.18-decimal fixed-point number. +/// @custom:smtchecker abstract-function-nondet +function exp2(uint256 x) pure returns (uint256 result) { + unchecked { + // Start from 0.5 in the 192.64-bit fixed-point format. + result = 0x800000000000000000000000000000000000000000000000; + + // The following logic multiplies the result by $\sqrt{2^{-i}}$ when the bit at position i is 1. Key points: + // + // 1. Intermediate results will not overflow, as the starting point is 2^191 and all magic factors are under 2^65. + // 2. The rationale for organizing the if statements into groups of 8 is gas savings. If the result of performing + // a bitwise AND operation between x and any value in the array [0x80; 0x40; 0x20; 0x10; 0x08; 0x04; 0x02; 0x01] is 1, + // we know that `x & 0xFF` is also 1. + if (x & 0xFF00000000000000 > 0) { + if (x & 0x8000000000000000 > 0) { + result = (result * 0x16A09E667F3BCC909) >> 64; + } + if (x & 0x4000000000000000 > 0) { + result = (result * 0x1306FE0A31B7152DF) >> 64; + } + if (x & 0x2000000000000000 > 0) { + result = (result * 0x1172B83C7D517ADCE) >> 64; + } + if (x & 0x1000000000000000 > 0) { + result = (result * 0x10B5586CF9890F62A) >> 64; + } + if (x & 0x800000000000000 > 0) { + result = (result * 0x1059B0D31585743AE) >> 64; + } + if (x & 0x400000000000000 > 0) { + result = (result * 0x102C9A3E778060EE7) >> 64; + } + if (x & 0x200000000000000 > 0) { + result = (result * 0x10163DA9FB33356D8) >> 64; + } + if (x & 0x100000000000000 > 0) { + result = (result * 0x100B1AFA5ABCBED61) >> 64; + } + } + + if (x & 0xFF000000000000 > 0) { + if (x & 0x80000000000000 > 0) { + result = (result * 0x10058C86DA1C09EA2) >> 64; + } + if (x & 0x40000000000000 > 0) { + result = (result * 0x1002C605E2E8CEC50) >> 64; + } + if (x & 0x20000000000000 > 0) { + result = (result * 0x100162F3904051FA1) >> 64; + } + if (x & 0x10000000000000 > 0) { + result = (result * 0x1000B175EFFDC76BA) >> 64; + } + if (x & 0x8000000000000 > 0) { + result = (result * 0x100058BA01FB9F96D) >> 64; + } + if (x & 0x4000000000000 > 0) { + result = (result * 0x10002C5CC37DA9492) >> 64; + } + if (x & 0x2000000000000 > 0) { + result = (result * 0x1000162E525EE0547) >> 64; + } + if (x & 0x1000000000000 > 0) { + result = (result * 0x10000B17255775C04) >> 64; + } + } + + if (x & 0xFF0000000000 > 0) { + if (x & 0x800000000000 > 0) { + result = (result * 0x1000058B91B5BC9AE) >> 64; + } + if (x & 0x400000000000 > 0) { + result = (result * 0x100002C5C89D5EC6D) >> 64; + } + if (x & 0x200000000000 > 0) { + result = (result * 0x10000162E43F4F831) >> 64; + } + if (x & 0x100000000000 > 0) { + result = (result * 0x100000B1721BCFC9A) >> 64; + } + if (x & 0x80000000000 > 0) { + result = (result * 0x10000058B90CF1E6E) >> 64; + } + if (x & 0x40000000000 > 0) { + result = (result * 0x1000002C5C863B73F) >> 64; + } + if (x & 0x20000000000 > 0) { + result = (result * 0x100000162E430E5A2) >> 64; + } + if (x & 0x10000000000 > 0) { + result = (result * 0x1000000B172183551) >> 64; + } + } + + if (x & 0xFF00000000 > 0) { + if (x & 0x8000000000 > 0) { + result = (result * 0x100000058B90C0B49) >> 64; + } + if (x & 0x4000000000 > 0) { + result = (result * 0x10000002C5C8601CC) >> 64; + } + if (x & 0x2000000000 > 0) { + result = (result * 0x1000000162E42FFF0) >> 64; + } + if (x & 0x1000000000 > 0) { + result = (result * 0x10000000B17217FBB) >> 64; + } + if (x & 0x800000000 > 0) { + result = (result * 0x1000000058B90BFCE) >> 64; + } + if (x & 0x400000000 > 0) { + result = (result * 0x100000002C5C85FE3) >> 64; + } + if (x & 0x200000000 > 0) { + result = (result * 0x10000000162E42FF1) >> 64; + } + if (x & 0x100000000 > 0) { + result = (result * 0x100000000B17217F8) >> 64; + } + } + + if (x & 0xFF000000 > 0) { + if (x & 0x80000000 > 0) { + result = (result * 0x10000000058B90BFC) >> 64; + } + if (x & 0x40000000 > 0) { + result = (result * 0x1000000002C5C85FE) >> 64; + } + if (x & 0x20000000 > 0) { + result = (result * 0x100000000162E42FF) >> 64; + } + if (x & 0x10000000 > 0) { + result = (result * 0x1000000000B17217F) >> 64; + } + if (x & 0x8000000 > 0) { + result = (result * 0x100000000058B90C0) >> 64; + } + if (x & 0x4000000 > 0) { + result = (result * 0x10000000002C5C860) >> 64; + } + if (x & 0x2000000 > 0) { + result = (result * 0x1000000000162E430) >> 64; + } + if (x & 0x1000000 > 0) { + result = (result * 0x10000000000B17218) >> 64; + } + } + + if (x & 0xFF0000 > 0) { + if (x & 0x800000 > 0) { + result = (result * 0x1000000000058B90C) >> 64; + } + if (x & 0x400000 > 0) { + result = (result * 0x100000000002C5C86) >> 64; + } + if (x & 0x200000 > 0) { + result = (result * 0x10000000000162E43) >> 64; + } + if (x & 0x100000 > 0) { + result = (result * 0x100000000000B1721) >> 64; + } + if (x & 0x80000 > 0) { + result = (result * 0x10000000000058B91) >> 64; + } + if (x & 0x40000 > 0) { + result = (result * 0x1000000000002C5C8) >> 64; + } + if (x & 0x20000 > 0) { + result = (result * 0x100000000000162E4) >> 64; + } + if (x & 0x10000 > 0) { + result = (result * 0x1000000000000B172) >> 64; + } + } + + if (x & 0xFF00 > 0) { + if (x & 0x8000 > 0) { + result = (result * 0x100000000000058B9) >> 64; + } + if (x & 0x4000 > 0) { + result = (result * 0x10000000000002C5D) >> 64; + } + if (x & 0x2000 > 0) { + result = (result * 0x1000000000000162E) >> 64; + } + if (x & 0x1000 > 0) { + result = (result * 0x10000000000000B17) >> 64; + } + if (x & 0x800 > 0) { + result = (result * 0x1000000000000058C) >> 64; + } + if (x & 0x400 > 0) { + result = (result * 0x100000000000002C6) >> 64; + } + if (x & 0x200 > 0) { + result = (result * 0x10000000000000163) >> 64; + } + if (x & 0x100 > 0) { + result = (result * 0x100000000000000B1) >> 64; + } + } + + if (x & 0xFF > 0) { + if (x & 0x80 > 0) { + result = (result * 0x10000000000000059) >> 64; + } + if (x & 0x40 > 0) { + result = (result * 0x1000000000000002C) >> 64; + } + if (x & 0x20 > 0) { + result = (result * 0x10000000000000016) >> 64; + } + if (x & 0x10 > 0) { + result = (result * 0x1000000000000000B) >> 64; + } + if (x & 0x8 > 0) { + result = (result * 0x10000000000000006) >> 64; + } + if (x & 0x4 > 0) { + result = (result * 0x10000000000000003) >> 64; + } + if (x & 0x2 > 0) { + result = (result * 0x10000000000000001) >> 64; + } + if (x & 0x1 > 0) { + result = (result * 0x10000000000000001) >> 64; + } + } + + // In the code snippet below, two operations are executed simultaneously: + // + // 1. The result is multiplied by $(2^n + 1)$, where $2^n$ represents the integer part, and the additional 1 + // accounts for the initial guess of 0.5. This is achieved by subtracting from 191 instead of 192. + // 2. The result is then converted to an unsigned 60.18-decimal fixed-point format. + // + // The underlying logic is based on the relationship $2^{191-ip} = 2^{ip} / 2^{191}$, where $ip$ denotes the, + // integer part, $2^n$. + result *= UNIT; + result >>= (191 - (x >> 64)); + } +} + +/// @notice Finds the zero-based index of the first 1 in the binary representation of x. +/// +/// @dev See the note on "msb" in this Wikipedia article: https://en.wikipedia.org/wiki/Find_first_set +/// +/// Each step in this implementation is equivalent to this high-level code: +/// +/// ```solidity +/// if (x >= 2 ** 128) { +/// x >>= 128; +/// result += 128; +/// } +/// ``` +/// +/// Where 128 is replaced with each respective power of two factor. See the full high-level implementation here: +/// https://gist.github.com/PaulRBerg/f932f8693f2733e30c4d479e8e980948 +/// +/// The Yul instructions used below are: +/// +/// - "gt" is "greater than" +/// - "or" is the OR bitwise operator +/// - "shl" is "shift left" +/// - "shr" is "shift right" +/// +/// @param x The uint256 number for which to find the index of the most significant bit. +/// @return result The index of the most significant bit as a uint256. +/// @custom:smtchecker abstract-function-nondet +function msb(uint256 x) pure returns (uint256 result) { + // 2^128 + assembly ("memory-safe") { + let factor := shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) + x := shr(factor, x) + result := or(result, factor) + } + // 2^64 + assembly ("memory-safe") { + let factor := shl(6, gt(x, 0xFFFFFFFFFFFFFFFF)) + x := shr(factor, x) + result := or(result, factor) + } + // 2^32 + assembly ("memory-safe") { + let factor := shl(5, gt(x, 0xFFFFFFFF)) + x := shr(factor, x) + result := or(result, factor) + } + // 2^16 + assembly ("memory-safe") { + let factor := shl(4, gt(x, 0xFFFF)) + x := shr(factor, x) + result := or(result, factor) + } + // 2^8 + assembly ("memory-safe") { + let factor := shl(3, gt(x, 0xFF)) + x := shr(factor, x) + result := or(result, factor) + } + // 2^4 + assembly ("memory-safe") { + let factor := shl(2, gt(x, 0xF)) + x := shr(factor, x) + result := or(result, factor) + } + // 2^2 + assembly ("memory-safe") { + let factor := shl(1, gt(x, 0x3)) + x := shr(factor, x) + result := or(result, factor) + } + // 2^1 + // No need to shift x any more. + assembly ("memory-safe") { + let factor := gt(x, 0x1) + result := or(result, factor) + } +} + +/// @notice Calculates x*y÷denominator with 512-bit precision. +/// +/// @dev Credits to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv. +/// +/// Notes: +/// - The result is rounded toward zero. +/// +/// Requirements: +/// - The denominator must not be zero. +/// - The result must fit in uint256. +/// +/// @param x The multiplicand as a uint256. +/// @param y The multiplier as a uint256. +/// @param denominator The divisor as a uint256. +/// @return result The result as a uint256. +/// @custom:smtchecker abstract-function-nondet +function mulDiv(uint256 x, uint256 y, uint256 denominator) pure returns (uint256 result) { + // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use + // use the Chinese Remainder Theorem to reconstruct the 512-bit result. The result is stored in two 256 + // variables such that product = prod1 * 2^256 + prod0. + uint256 prod0; // Least significant 256 bits of the product + uint256 prod1; // Most significant 256 bits of the product + assembly ("memory-safe") { + let mm := mulmod(x, y, not(0)) + prod0 := mul(x, y) + prod1 := sub(sub(mm, prod0), lt(mm, prod0)) + } + + // Handle non-overflow cases, 256 by 256 division. + if (prod1 == 0) { + unchecked { + return prod0 / denominator; + } + } + + // Make sure the result is less than 2^256. Also prevents denominator == 0. + if (prod1 >= denominator) { + revert PRBMath_MulDiv_Overflow(x, y, denominator); + } + + //////////////////////////////////////////////////////////////////////////// + // 512 by 256 division + //////////////////////////////////////////////////////////////////////////// + + // Make division exact by subtracting the remainder from [prod1 prod0]. + uint256 remainder; + assembly ("memory-safe") { + // Compute remainder using the mulmod Yul instruction. + remainder := mulmod(x, y, denominator) + + // Subtract 256 bit number from 512-bit number. + prod1 := sub(prod1, gt(remainder, prod0)) + prod0 := sub(prod0, remainder) + } + + unchecked { + // Calculate the largest power of two divisor of the denominator using the unary operator ~. This operation cannot overflow + // because the denominator cannot be zero at this point in the function execution. The result is always >= 1. + // For more detail, see https://cs.stackexchange.com/q/138556/92363. + uint256 lpotdod = denominator & (~denominator + 1); + uint256 flippedLpotdod; + + assembly ("memory-safe") { + // Factor powers of two out of denominator. + denominator := div(denominator, lpotdod) + + // Divide [prod1 prod0] by lpotdod. + prod0 := div(prod0, lpotdod) + + // Get the flipped value `2^256 / lpotdod`. If the `lpotdod` is zero, the flipped value is one. + // `sub(0, lpotdod)` produces the two's complement version of `lpotdod`, which is equivalent to flipping all the bits. + // However, `div` interprets this value as an unsigned value: https://ethereum.stackexchange.com/q/147168/24693 + flippedLpotdod := add(div(sub(0, lpotdod), lpotdod), 1) + } + + // Shift in bits from prod1 into prod0. + prod0 |= prod1 * flippedLpotdod; + + // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such + // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for + // four bits. That is, denominator * inv = 1 mod 2^4. + uint256 inverse = (3 * denominator) ^ 2; + + // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works + // in modular arithmetic, doubling the correct bits in each step. + inverse *= 2 - denominator * inverse; // inverse mod 2^8 + inverse *= 2 - denominator * inverse; // inverse mod 2^16 + inverse *= 2 - denominator * inverse; // inverse mod 2^32 + inverse *= 2 - denominator * inverse; // inverse mod 2^64 + inverse *= 2 - denominator * inverse; // inverse mod 2^128 + inverse *= 2 - denominator * inverse; // inverse mod 2^256 + + // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. + // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is + // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 + // is no longer required. + result = prod0 * inverse; + } +} + +/// @notice Calculates x*y÷1e18 with 512-bit precision. +/// +/// @dev A variant of {mulDiv} with constant folding, i.e. in which the denominator is hard coded to 1e18. +/// +/// Notes: +/// - The body is purposely left uncommented; to understand how this works, see the documentation in {mulDiv}. +/// - The result is rounded toward zero. +/// - We take as an axiom that the result cannot be `MAX_UINT256` when x and y solve the following system of equations: +/// +/// $$ +/// \begin{cases} +/// x * y = MAX\_UINT256 * UNIT \\ +/// (x * y) \% UNIT \geq \frac{UNIT}{2} +/// \end{cases} +/// $$ +/// +/// Requirements: +/// - Refer to the requirements in {mulDiv}. +/// - The result must fit in uint256. +/// +/// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number. +/// @param y The multiplier as an unsigned 60.18-decimal fixed-point number. +/// @return result The result as an unsigned 60.18-decimal fixed-point number. +/// @custom:smtchecker abstract-function-nondet +function mulDiv18(uint256 x, uint256 y) pure returns (uint256 result) { + uint256 prod0; + uint256 prod1; + assembly ("memory-safe") { + let mm := mulmod(x, y, not(0)) + prod0 := mul(x, y) + prod1 := sub(sub(mm, prod0), lt(mm, prod0)) + } + + if (prod1 == 0) { + unchecked { + return prod0 / UNIT; + } + } + + if (prod1 >= UNIT) { + revert PRBMath_MulDiv18_Overflow(x, y); + } + + uint256 remainder; + assembly ("memory-safe") { + remainder := mulmod(x, y, UNIT) + result := + mul( + or( + div(sub(prod0, remainder), UNIT_LPOTD), + mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, UNIT_LPOTD), UNIT_LPOTD), 1)) + ), + UNIT_INVERSE + ) + } +} + +/// @notice Calculates x*y÷denominator with 512-bit precision. +/// +/// @dev This is an extension of {mulDiv} for signed numbers, which works by computing the signs and the absolute values separately. +/// +/// Notes: +/// - The result is rounded toward zero. +/// +/// Requirements: +/// - Refer to the requirements in {mulDiv}. +/// - None of the inputs can be `type(int256).min`. +/// - The result must fit in int256. +/// +/// @param x The multiplicand as an int256. +/// @param y The multiplier as an int256. +/// @param denominator The divisor as an int256. +/// @return result The result as an int256. +/// @custom:smtchecker abstract-function-nondet +function mulDivSigned(int256 x, int256 y, int256 denominator) pure returns (int256 result) { + if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) { + revert PRBMath_MulDivSigned_InputTooSmall(); + } + + // Get hold of the absolute values of x, y and the denominator. + uint256 xAbs; + uint256 yAbs; + uint256 dAbs; + unchecked { + xAbs = x < 0 ? uint256(-x) : uint256(x); + yAbs = y < 0 ? uint256(-y) : uint256(y); + dAbs = denominator < 0 ? uint256(-denominator) : uint256(denominator); + } + + // Compute the absolute value of x*y÷denominator. The result must fit in int256. + uint256 resultAbs = mulDiv(xAbs, yAbs, dAbs); + if (resultAbs > uint256(type(int256).max)) { + revert PRBMath_MulDivSigned_Overflow(x, y); + } + + // Get the signs of x, y and the denominator. + uint256 sx; + uint256 sy; + uint256 sd; + assembly ("memory-safe") { + // "sgt" is the "signed greater than" assembly instruction and "sub(0,1)" is -1 in two's complement. + sx := sgt(x, sub(0, 1)) + sy := sgt(y, sub(0, 1)) + sd := sgt(denominator, sub(0, 1)) + } + + // XOR over sx, sy and sd. What this does is to check whether there are 1 or 3 negative signs in the inputs. + // If there are, the result should be negative. Otherwise, it should be positive. + unchecked { + result = sx ^ sy ^ sd == 0 ? -int256(resultAbs) : int256(resultAbs); + } +} + +/// @notice Calculates the square root of x using the Babylonian method. +/// +/// @dev See https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method. +/// +/// Notes: +/// - If x is not a perfect square, the result is rounded down. +/// - Credits to OpenZeppelin for the explanations in comments below. +/// +/// @param x The uint256 number for which to calculate the square root. +/// @return result The result as a uint256. +/// @custom:smtchecker abstract-function-nondet +function sqrt(uint256 x) pure returns (uint256 result) { + if (x == 0) { + return 0; + } + + // For our first guess, we calculate the biggest power of 2 which is smaller than the square root of x. + // + // We know that the "msb" (most significant bit) of x is a power of 2 such that we have: + // + // $$ + // msb(x) <= x <= 2*msb(x)$ + // $$ + // + // We write $msb(x)$ as $2^k$, and we get: + // + // $$ + // k = log_2(x) + // $$ + // + // Thus, we can write the initial inequality as: + // + // $$ + // 2^{log_2(x)} <= x <= 2*2^{log_2(x)+1} \\ + // sqrt(2^k) <= sqrt(x) < sqrt(2^{k+1}) \\ + // 2^{k/2} <= sqrt(x) < 2^{(k+1)/2} <= 2^{(k/2)+1} + // $$ + // + // Consequently, $2^{log_2(x) /2} is a good first approximation of sqrt(x) with at least one correct bit. + uint256 xAux = uint256(x); + result = 1; + if (xAux >= 2 ** 128) { + xAux >>= 128; + result <<= 64; + } + if (xAux >= 2 ** 64) { + xAux >>= 64; + result <<= 32; + } + if (xAux >= 2 ** 32) { + xAux >>= 32; + result <<= 16; + } + if (xAux >= 2 ** 16) { + xAux >>= 16; + result <<= 8; + } + if (xAux >= 2 ** 8) { + xAux >>= 8; + result <<= 4; + } + if (xAux >= 2 ** 4) { + xAux >>= 4; + result <<= 2; + } + if (xAux >= 2 ** 2) { + result <<= 1; + } + + // At this point, `result` is an estimation with at least one bit of precision. We know the true value has at + // most 128 bits, since it is the square root of a uint256. Newton's method converges quadratically (precision + // doubles at every iteration). We thus need at most 7 iteration to turn our partial result with one bit of + // precision into the expected uint128 result. + unchecked { + result = (result + x / result) >> 1; + result = (result + x / result) >> 1; + result = (result + x / result) >> 1; + result = (result + x / result) >> 1; + result = (result + x / result) >> 1; + result = (result + x / result) >> 1; + result = (result + x / result) >> 1; + + // If x is not a perfect square, round the result toward zero. + uint256 roundedResult = x / result; + if (result >= roundedResult) { + result = roundedResult; + } + } +} + + +// File contracts/interfaces/IUniswapV2Pair.sol + + +// Uniswap related interface +interface IUniswapV2Pair { + function totalSupply() external view returns (uint); + function token0() external view returns (address); + function token1() external view returns (address); + function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); +} + + +// File contracts/interfaces/IVotingEscrow.sol + + +/// @dev Interface for voting escrow. +interface IVotingEscrow { + /// @dev Gets the voting power. + /// @param account Account address. + function getVotes(address account) external view returns (uint256); +} + + +// File contracts/BondCalculator.sol + + + + +interface ITokenomics { + /// @dev Gets number of new units that were donated in the last epoch. + /// @return Number of new units. + function getLastEpochNumNewUnits() external view returns (uint256); +} + +/// @dev Only `owner` has a privilege, but the `sender` was provided. +/// @param sender Sender address. +/// @param owner Required sender address as an owner. +error OwnerOnly(address sender, address owner); + +/// @dev Value overflow. +/// @param provided Overflow value. +/// @param max Maximum possible value. +error Overflow(uint256 provided, uint256 max); + +/// @dev Provided zero address. +error ZeroAddress(); + +/// @dev Provided zero value. +error ZeroValue(); + +// Struct for discount factor params +// The size of the struct is 96 + 64 + 64 = 224 (1 slot) +struct DiscountParams { + // DAO set voting power limit for the bonding account + // This value is bound by the veOLAS total voting power + uint96 targetVotingPower; + // DAO set number of new units per epoch limit + // This number is bound by the total number of possible components and agents + uint64 targetNewUnits; + // DAO set weight factors + // The sum of factors cannot exceed the value of 10_000 (100% with a 0.01% step) + uint16[4] weightFactors; +} + +// The size of the struct is 160 + 32 + 160 + 96 = 256 + 192 (2 slots) +struct Product { + // priceLP (reserve0 / totalSupply or reserve1 / totalSupply) with 18 additional decimals + // priceLP = 2 * r0/L * 10^18 = 2*r0*10^18/sqrt(r0*r1) ~= 61 + 96 - sqrt(96 * 112) ~= 53 bits (if LP is balanced) + // or 2* r0/sqrt(r0) * 10^18 => 87 bits + 60 bits = 147 bits (if LP is unbalanced) + uint160 priceLP; + // Supply of remaining OLAS tokens + // After 10 years, the OLAS inflation rate is 2% per year. It would take 220+ years to reach 2^96 - 1 + uint96 supply; + // Token to accept as a payment + address token; + // Current OLAS payout + // This value is bound by the initial total supply + uint96 payout; + // Max bond vesting time + // 2^32 - 1 is enough to count 136 years starting from the year of 1970. This counter is safe until the year of 2106 + uint32 vesting; +} + +/// @title BondCalculator - Smart contract for bond calculation payout in exchange for OLAS tokens based on dynamic IDF. +/// @author Aleksandr Kuperman - +/// @author Andrey Lebedev - +/// @author Mariapia Moscatiello - +contract BondCalculator { + event OwnerUpdated(address indexed owner); + event DiscountParamsUpdated(DiscountParams newDiscountParams); + + // Maximum sum of discount factor weights + uint256 public constant MAX_SUM_WEIGHTS = 10_000; + // OLAS contract address + address public immutable olas; + // Tokenomics contract address + address public immutable tokenomics; + // veOLAS contract address + address public immutable ve; + + // Contract owner + address public owner; + // Discount params + DiscountParams public discountParams; + + + /// @dev Bond Calculator constructor. + /// @param _olas OLAS contract address. + /// @param _tokenomics Tokenomics contract address. + /// @param _ve veOLAS contract address. + /// @param _discountParams Discount factor parameters. + constructor(address _olas, address _tokenomics, address _ve, DiscountParams memory _discountParams) { + // Check for at least one zero contract address + if (_olas == address(0) || _tokenomics == address(0) || _ve == address(0)) { + revert ZeroAddress(); + } + + olas = _olas; + tokenomics = _tokenomics; + ve = _ve; + owner = msg.sender; + + // Check for zero values + if (_discountParams.targetNewUnits == 0 || _discountParams.targetVotingPower == 0) { + revert ZeroValue(); + } + // Check the sum of factors that cannot exceed the value of 10_000 (100% with a 0.01% step) + uint256 sumWeights; + for (uint256 i = 0; i < _discountParams.weightFactors.length; ++i) { + sumWeights += _discountParams.weightFactors[i]; + } + if (sumWeights > MAX_SUM_WEIGHTS) { + revert Overflow(sumWeights, MAX_SUM_WEIGHTS); + } + discountParams = _discountParams; + } + + /// @dev Changes contract owner address. + /// @param newOwner Address of a new owner. + function changeOwner(address newOwner) external { + // Check for the contract ownership + if (msg.sender != owner) { + revert OwnerOnly(msg.sender, owner); + } + + // Check for the zero address + if (newOwner == address(0)) { + revert ZeroAddress(); + } + + owner = newOwner; + emit OwnerUpdated(newOwner); + } + + /// @dev Changed inverse discount factor parameters. + /// @param newDiscountParams Struct of new discount parameters. + function changeDiscountParams(DiscountParams memory newDiscountParams) external { + // Check for the contract ownership + if (msg.sender != owner) { + revert OwnerOnly(msg.sender, owner); + } + + // Check for zero values + if (newDiscountParams.targetNewUnits == 0 || newDiscountParams.targetVotingPower == 0) { + revert ZeroValue(); + } + // Check the sum of factors that cannot exceed the value of 10_000 (100% with a 0.01% step) + uint256 sumWeights; + for (uint256 i = 0; i < newDiscountParams.weightFactors.length; ++i) { + sumWeights += newDiscountParams.weightFactors[i]; + } + if (sumWeights > MAX_SUM_WEIGHTS) { + revert Overflow(sumWeights, MAX_SUM_WEIGHTS); + } + + discountParams = newDiscountParams; + + emit DiscountParamsUpdated(newDiscountParams); + } + + /// @dev Calculated inverse discount factor based on bonding and account parameters. + /// @param account Account address. + /// @param bondVestingTime Bond vesting time. + /// @param productMaxVestingTime Product max vesting time. + /// @param productSupply Current product supply. + /// @param productPayout Current product payout. + /// @return idf Inverse discount factor in 18 decimals format. + function calculateIDF(address account, uint256 bondVestingTime, uint256 productMaxVestingTime, uint256 productSupply, + uint256 productPayout) public view returns (uint256 idf) { + + // Get the copy of the discount params + DiscountParams memory localParams = discountParams; + uint256 discountBooster; + + // First discount booster: booster = k1 * NumNewUnits(previous epoch) / TargetNewUnits(previous epoch) + // Check the number of new units coming from tokenomics vs the target number of new units + if (localParams.weightFactors[0] > 0) { + uint256 numNewUnits = ITokenomics(tokenomics).getLastEpochNumNewUnits(); + + // If the number of new units exceeds the target, bound by the target number + if (numNewUnits >= localParams.targetNewUnits) { + discountBooster = uint256(localParams.weightFactors[0]) * 1e18; + } else { + discountBooster = (uint256(localParams.weightFactors[0]) * numNewUnits * 1e18) / + uint256(localParams.targetNewUnits); + } + } + + // Second discount booster: booster += k2 * bondVestingTime / productMaxVestingTime + // Add vesting time discount booster + if (localParams.weightFactors[1] > 0) { + if (bondVestingTime == productMaxVestingTime) { + discountBooster += uint256(localParams.weightFactors[1]) * 1e18; + } else { + discountBooster += (uint256(localParams.weightFactors[1]) * bondVestingTime * 1e18) / productMaxVestingTime; + } + } + + // Third discount booster: booster += k3 * (1 - productPayout(at bonding time) / productSupply) + // Add product supply discount booster + if (localParams.weightFactors[2] > 0) { + if (productPayout == 0) { + discountBooster += uint256(localParams.weightFactors[2]) * 1e18; + } else { + // Get the total product supply + productSupply = productSupply + productPayout; + discountBooster += uint256(localParams.weightFactors[2]) * (1e18 - ((productPayout * 1e18) / productSupply)); + } + } + + // Fourth discount booster: booster += k4 * getVotes(bonding account) / targetVotingPower + // Check the veOLAS balance of a bonding account + if (localParams.weightFactors[3] > 0) { + uint256 vPower = IVotingEscrow(ve).getVotes(account); + + // If the number of new units exceeds the target, bound by the target number + if (vPower >= localParams.targetVotingPower) { + discountBooster += uint256(localParams.weightFactors[3]) * 1e18; + } else { + discountBooster += (uint256(localParams.weightFactors[3]) * vPower * 1e18) / + uint256(localParams.targetVotingPower); + } + } + + // Normalize discount booster by the max sum of weights + discountBooster /= MAX_SUM_WEIGHTS; + + // IDF = 1 + normalized booster + idf = 1e18 + discountBooster; + } + + /// @dev Calculates the amount of OLAS tokens based on the bonding calculator mechanism accounting for dynamic IDF. + /// @param account Account address. + /// @param tokenAmount LP token amount. + /// @param priceLP LP token price. + /// @param bondVestingTime Bond vesting time. + /// @param productMaxVestingTime Product max vesting time. + /// @param productSupply Current product supply. + /// @param productPayout Current product payout. + /// @return amountOLAS Resulting amount of OLAS tokens. + function calculatePayoutOLAS( + address account, + uint256 tokenAmount, + uint256 priceLP, + uint256 bondVestingTime, + uint256 productMaxVestingTime, + uint256 productSupply, + uint256 productPayout + ) external view returns (uint256 amountOLAS) { + // The result is divided by additional 1e18, since it was multiplied by in the current LP price calculation + // The resulting amountDF can not overflow by the following calculations: idf = 64 bits; + // priceLP = 2 * r0/L * 10^18 = 2*r0*10^18/sqrt(r0*r1) ~= 61 + 96 - sqrt(96 * 112) ~= 53 bits (if LP is balanced) + // or 2* r0/sqrt(r0) * 10^18 => 87 bits + 60 bits = 147 bits (if LP is unbalanced); + // tokenAmount is of the order of sqrt(r0*r1) ~ 104 bits (if balanced) or sqrt(96) ~ 10 bits (if max unbalanced); + // overall: 64 + 53 + 104 = 221 < 256 - regular case if LP is balanced, and 64 + 147 + 10 = 221 < 256 if unbalanced + // mulDiv will correctly fit the total amount up to the value of max uint256, i.e., max of priceLP and max of tokenAmount, + // however their multiplication can not be bigger than the max of uint192 + uint256 totalTokenValue = mulDiv(priceLP, tokenAmount, 1); + // Check for the cumulative LP tokens value limit + if (totalTokenValue > type(uint192).max) { + revert Overflow(totalTokenValue, type(uint192).max); + } + + // Calculate the dynamic inverse discount factor + uint256 idf = calculateIDF(account, bondVestingTime, productMaxVestingTime, productSupply, productPayout); + + // Amount with the discount factor is IDF * priceLP * tokenAmount / 1e36 + // At this point of time IDF is bound by the max of uint64, and totalTokenValue is no bigger than the max of uint192 + amountOLAS = (idf * totalTokenValue) / 1e36; + } + + /// @dev Gets current reserves of OLAS / totalSupply of Uniswap V2-like LP tokens. + /// @notice The price LP calculation is based on the UniswapV2Pair contract. + /// @param token Token address. + /// @return priceLP Resulting reserveX / totalSupply ratio with 18 decimals. + function getCurrentPriceLP(address token) external view returns (uint256 priceLP) { + IUniswapV2Pair pair = IUniswapV2Pair(token); + uint256 totalSupply = pair.totalSupply(); + if (totalSupply > 0) { + address token0 = pair.token0(); + address token1 = pair.token1(); + uint256 reserve0; + uint256 reserve1; + // requires low gas + (reserve0, reserve1, ) = pair.getReserves(); + // token0 != olas && token1 != olas, this should never happen + if (token0 == olas || token1 == olas) { + // If OLAS is in token0, assign its reserve to reserve1, otherwise the reserve1 is already correct + if (token0 == olas) { + reserve1 = reserve0; + } + // Calculate the LP price based on reserves and totalSupply ratio multiplied by 1e18 + // Inspired by: https://github.com/curvefi/curve-contract/blob/master/contracts/pool-templates/base/SwapTemplateBase.vy#L262 + priceLP = (reserve1 * 1e18) / totalSupply; + } + } + } + + function getDiscountParams() external view returns (DiscountParams memory) { + return discountParams; + } +} diff --git a/audits/internal6/analysis/contracts/Depository-flatten.sol b/audits/internal6/analysis/contracts/Depository-flatten.sol new file mode 100644 index 00000000..8523c997 --- /dev/null +++ b/audits/internal6/analysis/contracts/Depository-flatten.sol @@ -0,0 +1,1085 @@ +// Sources flattened with hardhat v2.22.4 https://hardhat.org + +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +/// @dev Errors. +interface IErrorsTokenomics { + /// @dev Only `manager` has a privilege, but the `sender` was provided. + /// @param sender Sender address. + /// @param manager Required sender address as a manager. + error ManagerOnly(address sender, address manager); + + /// @dev Only `owner` has a privilege, but the `sender` was provided. + /// @param sender Sender address. + /// @param owner Required sender address as an owner. + error OwnerOnly(address sender, address owner); + + /// @dev Provided zero address. + error ZeroAddress(); + + /// @dev Wrong length of two arrays. + /// @param numValues1 Number of values in a first array. + /// @param numValues2 Number of values in a second array. + error WrongArrayLength(uint256 numValues1, uint256 numValues2); + + /// @dev Service Id does not exist in registry records. + /// @param serviceId Service Id. + error ServiceDoesNotExist(uint256 serviceId); + + /// @dev Zero value when it has to be different from zero. + error ZeroValue(); + + /// @dev Non-zero value when it has to be zero. + error NonZeroValue(); + + /// @dev Value overflow. + /// @param provided Overflow value. + /// @param max Maximum possible value. + error Overflow(uint256 provided, uint256 max); + + /// @dev Service was never deployed. + /// @param serviceId Service Id. + error ServiceNeverDeployed(uint256 serviceId); + + /// @dev Token is disabled or not whitelisted. + /// @param tokenAddress Address of a token. + error UnauthorizedToken(address tokenAddress); + + /// @dev Provided token address is incorrect. + /// @param provided Provided token address. + /// @param expected Expected token address. + error WrongTokenAddress(address provided, address expected); + + /// @dev Bond is not redeemable (does not exist or not matured). + /// @param bondId Bond Id. + error BondNotRedeemable(uint256 bondId); + + /// @dev The product is expired. + /// @param tokenAddress Address of a token. + /// @param productId Product Id. + /// @param deadline The program expiry time. + /// @param curTime Current timestamp. + error ProductExpired(address tokenAddress, uint256 productId, uint256 deadline, uint256 curTime); + + /// @dev The product is already closed. + /// @param productId Product Id. + error ProductClosed(uint256 productId); + + /// @dev The product supply is low for the requested payout. + /// @param tokenAddress Address of a token. + /// @param productId Product Id. + /// @param requested Requested payout. + /// @param actual Actual supply left. + error ProductSupplyLow(address tokenAddress, uint256 productId, uint256 requested, uint256 actual); + + /// @dev Received lower value than the expected one. + /// @param provided Provided value is lower. + /// @param expected Expected value. + error LowerThan(uint256 provided, uint256 expected); + + /// @dev Wrong amount received / provided. + /// @param provided Provided amount. + /// @param expected Expected amount. + error WrongAmount(uint256 provided, uint256 expected); + + /// @dev Insufficient token allowance. + /// @param provided Provided amount. + /// @param expected Minimum expected amount. + error InsufficientAllowance(uint256 provided, uint256 expected); + + /// @dev Failure of a transfer. + /// @param token Address of a token. + /// @param from Address `from`. + /// @param to Address `to`. + /// @param amount Token amount. + error TransferFailed(address token, address from, address to, uint256 amount); + + /// @dev Incentives claim has failed. + /// @param account Account address. + /// @param reward Reward amount. + /// @param topUp Top-up amount. + error ClaimIncentivesFailed(address account, uint256 reward, uint256 topUp); + + /// @dev Caught reentrancy violation. + error ReentrancyGuard(); + + /// @dev Failure of treasury re-balance during the reward allocation. + /// @param epochNumber Epoch number. + error TreasuryRebalanceFailed(uint256 epochNumber); + + /// @dev Operation with a wrong component / agent Id. + /// @param unitId Component / agent Id. + /// @param unitType Type of the unit (component / agent). + error WrongUnitId(uint256 unitId, uint256 unitType); + + /// @dev The donator address is blacklisted. + /// @param account Donator account address. + error DonatorBlacklisted(address account); + + /// @dev The contract is already initialized. + error AlreadyInitialized(); + + /// @dev The contract has to be delegate-called via proxy. + error DelegatecallOnly(); + + /// @dev The contract is paused. + error Paused(); + + /// @dev Caught an operation that is not supposed to happen in the same block. + error SameBlockNumberViolation(); +} + + +// File contracts/interfaces/IToken.sol +/// @dev Generic token interface for IERC20 and IERC721 tokens. +interface IToken { + /// @dev Gets the amount of tokens owned by a specified account. + /// @param account Account address. + /// @return Amount of tokens owned. + function balanceOf(address account) external view returns (uint256); + + /// @dev Gets the owner of the token Id. + /// @param tokenId Token Id. + /// @return Token Id owner address. + function ownerOf(uint256 tokenId) external view returns (address); + + /// @dev Gets the total amount of tokens stored by the contract. + /// @return Amount of tokens. + function totalSupply() external view returns (uint256); + + /// @dev Transfers the token amount. + /// @param to Address to transfer to. + /// @param amount The amount to transfer. + /// @return True if the function execution is successful. + function transfer(address to, uint256 amount) external returns (bool); + + /// @dev Gets remaining number of tokens that the `spender` can transfer on behalf of `owner`. + /// @param owner Token owner. + /// @param spender Account address that is able to transfer tokens on behalf of the owner. + /// @return Token amount allowed to be transferred. + function allowance(address owner, address spender) external view returns (uint256); + + /// @dev Sets `amount` as the allowance of `spender` over the caller's tokens. + /// @param spender Account address that will be able to transfer tokens on behalf of the caller. + /// @param amount Token amount. + /// @return True if the function execution is successful. + function approve(address spender, uint256 amount) external returns (bool); + + /// @dev Transfers the token amount that was previously approved up until the maximum allowance. + /// @param from Account address to transfer from. + /// @param to Account address to transfer to. + /// @param amount Amount to transfer to. + /// @return True if the function execution is successful. + function transferFrom(address from, address to, uint256 amount) external returns (bool); +} + + +// File contracts/interfaces/ITokenomics.sol +/// @dev Interface for tokenomics management. +interface ITokenomics { + /// @dev Gets effective bond (bond left). + /// @return Effective bond. + function effectiveBond() external pure returns (uint256); + + /// @dev Record global data to the checkpoint + function checkpoint() external returns (bool); + + /// @dev Tracks the deposited ETH service donations during the current epoch. + /// @notice This function is only called by the treasury where the validity of arrays and values has been performed. + /// @param donator Donator account address. + /// @param serviceIds Set of service Ids. + /// @param amounts Correspondent set of ETH amounts provided by services. + /// @param donationETH Overall service donation amount in ETH. + function trackServiceDonations( + address donator, + uint256[] memory serviceIds, + uint256[] memory amounts, + uint256 donationETH + ) external; + + /// @dev Reserves OLAS amount from the effective bond to be minted during a bond program. + /// @notice Programs exceeding the limit in the epoch are not allowed. + /// @param amount Requested amount for the bond program. + /// @return True if effective bond threshold is not reached. + function reserveAmountForBondProgram(uint256 amount) external returns(bool); + + /// @dev Refunds unused bond program amount. + /// @param amount Amount to be refunded from the bond program. + function refundFromBondProgram(uint256 amount) external; + + /// @dev Gets component / agent owner incentives and clears the balances. + /// @param account Account address. + /// @param unitTypes Set of unit types (component / agent). + /// @param unitIds Set of corresponding unit Ids where account is the owner. + /// @return reward Reward amount. + /// @return topUp Top-up amount. + function accountOwnerIncentives(address account, uint256[] memory unitTypes, uint256[] memory unitIds) external + returns (uint256 reward, uint256 topUp); + + /// @dev Gets inverse discount factor with the multiple of 1e18 of the last epoch. + /// @return idf Discount factor with the multiple of 1e18. + function getLastIDF() external view returns (uint256 idf); + + /// @dev Gets the service registry contract address + /// @return Service registry contract address; + function serviceRegistry() external view returns (address); +} + + +// File contracts/interfaces/ITreasury.sol +/// @dev Interface for treasury management. +interface ITreasury { + /// @dev Allows approved address to deposit an asset for OLAS. + /// @param account Account address making a deposit of LP tokens for OLAS. + /// @param tokenAmount Token amount to get OLAS for. + /// @param token Token address. + /// @param olaMintAmount Amount of OLAS token issued. + function depositTokenForOLAS(address account, uint256 tokenAmount, address token, uint256 olaMintAmount) external; + + /// @dev Deposits service donations in ETH. + /// @param serviceIds Set of service Ids. + /// @param amounts Set of corresponding amounts deposited on behalf of each service Id. + function depositServiceDonationsETH(uint256[] memory serviceIds, uint256[] memory amounts) external payable; + + /// @dev Gets information about token being enabled. + /// @param token Token address. + /// @return enabled True is token is enabled. + function isEnabled(address token) external view returns (bool enabled); + + /// @dev Withdraws ETH and / or OLAS amounts to the requested account address. + /// @notice Only dispenser contract can call this function. + /// @notice Reentrancy guard is on a dispenser side. + /// @notice Zero account address is not possible, since the dispenser contract interacts with msg.sender. + /// @param account Account address. + /// @param accountRewards Amount of account rewards. + /// @param accountTopUps Amount of account top-ups. + /// @return success True if the function execution is successful. + function withdrawToAccount(address account, uint256 accountRewards, uint256 accountTopUps) external returns (bool success); + + /// @dev Re-balances treasury funds to account for the treasury reward for a specific epoch. + /// @param treasuryRewards Treasury rewards. + /// @return success True, if the function execution is successful. + function rebalanceTreasury(uint256 treasuryRewards) external returns (bool success); +} + + +// File lib/solmate/src/tokens/ERC721.sol +/// @notice Modern, minimalist, and gas efficient ERC-721 implementation. +/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol) +abstract contract ERC721 { + /*////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + event Transfer(address indexed from, address indexed to, uint256 indexed id); + + event Approval(address indexed owner, address indexed spender, uint256 indexed id); + + event ApprovalForAll(address indexed owner, address indexed operator, bool approved); + + /*////////////////////////////////////////////////////////////// + METADATA STORAGE/LOGIC + //////////////////////////////////////////////////////////////*/ + + string public name; + + string public symbol; + + function tokenURI(uint256 id) public view virtual returns (string memory); + + /*////////////////////////////////////////////////////////////// + ERC721 BALANCE/OWNER STORAGE + //////////////////////////////////////////////////////////////*/ + + mapping(uint256 => address) internal _ownerOf; + + mapping(address => uint256) internal _balanceOf; + + function ownerOf(uint256 id) public view virtual returns (address owner) { + require((owner = _ownerOf[id]) != address(0), "NOT_MINTED"); + } + + function balanceOf(address owner) public view virtual returns (uint256) { + require(owner != address(0), "ZERO_ADDRESS"); + + return _balanceOf[owner]; + } + + /*////////////////////////////////////////////////////////////// + ERC721 APPROVAL STORAGE + //////////////////////////////////////////////////////////////*/ + + mapping(uint256 => address) public getApproved; + + mapping(address => mapping(address => bool)) public isApprovedForAll; + + /*////////////////////////////////////////////////////////////// + CONSTRUCTOR + //////////////////////////////////////////////////////////////*/ + + constructor(string memory _name, string memory _symbol) { + name = _name; + symbol = _symbol; + } + + /*////////////////////////////////////////////////////////////// + ERC721 LOGIC + //////////////////////////////////////////////////////////////*/ + + function approve(address spender, uint256 id) public virtual { + address owner = _ownerOf[id]; + + require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED"); + + getApproved[id] = spender; + + emit Approval(owner, spender, id); + } + + function setApprovalForAll(address operator, bool approved) public virtual { + isApprovedForAll[msg.sender][operator] = approved; + + emit ApprovalForAll(msg.sender, operator, approved); + } + + function transferFrom( + address from, + address to, + uint256 id + ) public virtual { + require(from == _ownerOf[id], "WRONG_FROM"); + + require(to != address(0), "INVALID_RECIPIENT"); + + require( + msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id], + "NOT_AUTHORIZED" + ); + + // Underflow of the sender's balance is impossible because we check for + // ownership above and the recipient's balance can't realistically overflow. + unchecked { + _balanceOf[from]--; + + _balanceOf[to]++; + } + + _ownerOf[id] = to; + + delete getApproved[id]; + + emit Transfer(from, to, id); + } + + function safeTransferFrom( + address from, + address to, + uint256 id + ) public virtual { + transferFrom(from, to, id); + + if (to.code.length != 0) + require( + ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") == + ERC721TokenReceiver.onERC721Received.selector, + "UNSAFE_RECIPIENT" + ); + } + + function safeTransferFrom( + address from, + address to, + uint256 id, + bytes calldata data + ) public virtual { + transferFrom(from, to, id); + + if (to.code.length != 0) + require( + ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) == + ERC721TokenReceiver.onERC721Received.selector, + "UNSAFE_RECIPIENT" + ); + } + + /*////////////////////////////////////////////////////////////// + ERC165 LOGIC + //////////////////////////////////////////////////////////////*/ + + function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { + return + interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 + interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721 + interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata + } + + /*////////////////////////////////////////////////////////////// + INTERNAL MINT/BURN LOGIC + //////////////////////////////////////////////////////////////*/ + + function _mint(address to, uint256 id) internal virtual { + require(to != address(0), "INVALID_RECIPIENT"); + + require(_ownerOf[id] == address(0), "ALREADY_MINTED"); + + // Counter overflow is incredibly unrealistic. + unchecked { + _balanceOf[to]++; + } + + _ownerOf[id] = to; + + emit Transfer(address(0), to, id); + } + + function _burn(uint256 id) internal virtual { + address owner = _ownerOf[id]; + + require(owner != address(0), "NOT_MINTED"); + + // Ownership check above ensures no underflow. + unchecked { + _balanceOf[owner]--; + } + + delete _ownerOf[id]; + + delete getApproved[id]; + + emit Transfer(owner, address(0), id); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL SAFE MINT LOGIC + //////////////////////////////////////////////////////////////*/ + + function _safeMint(address to, uint256 id) internal virtual { + _mint(to, id); + + if (to.code.length != 0) + require( + ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") == + ERC721TokenReceiver.onERC721Received.selector, + "UNSAFE_RECIPIENT" + ); + } + + function _safeMint( + address to, + uint256 id, + bytes memory data + ) internal virtual { + _mint(to, id); + + if (to.code.length != 0) + require( + ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) == + ERC721TokenReceiver.onERC721Received.selector, + "UNSAFE_RECIPIENT" + ); + } +} + +/// @notice A generic interface for a contract which properly accepts ERC721 tokens. +/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol) +abstract contract ERC721TokenReceiver { + function onERC721Received( + address, + address, + uint256, + bytes calldata + ) external virtual returns (bytes4) { + return ERC721TokenReceiver.onERC721Received.selector; + } +} + + +// File contracts/Depository.sol +interface IBondCalculator { + /// @dev Calculates the amount of OLAS tokens based on the bonding calculator mechanism accounting for dynamic IDF. + /// @param account Account address. + /// @param tokenAmount LP token amount. + /// @param priceLP LP token price. + /// @param bondVestingTime Bond vesting time. + /// @param productMaxVestingTime Product max vesting time. + /// @param productSupply Current product supply. + /// @param productPayout Current product payout. + /// @return amountOLAS Resulting amount of OLAS tokens. + function calculatePayoutOLAS( + address account, + uint256 tokenAmount, + uint256 priceLP, + uint256 bondVestingTime, + uint256 productMaxVestingTime, + uint256 productSupply, + uint256 productPayout + ) external view returns (uint256 amountOLAS); + + /// @dev Gets current reserves of OLAS / totalSupply of Uniswap V2-like LP tokens. + /// @param token Token address. + /// @return priceLP Resulting reserveX / totalSupply ratio with 18 decimals. + function getCurrentPriceLP(address token) external view returns (uint256 priceLP); +} + +/// @dev Wrong amount received / provided. +/// @param provided Provided amount. +/// @param expected Expected amount. +error WrongAmount(uint256 provided, uint256 expected); + +/* +* In this contract we consider OLAS tokens. The initial numbers will be as follows: +* - For the first 10 years there will be the cap of 1 billion (1e27) tokens; +* - After 10 years, the inflation rate is capped at 2% per year. +* Starting from a year 11, the maximum number of tokens that can be reached per the year x is 1e27 * (1.02)^x. +* To make sure that a unit(n) does not overflow the total supply during the year x, we have to check that +* 2^n - 1 >= 1e27 * (1.02)^x. We limit n by 96, thus it would take 220+ years to reach that total supply. +* +* We then limit each time variable to last until the value of 2^32 - 1 in seconds. +* 2^32 - 1 gives 136+ years counted in seconds starting from the year 1970. +* Thus, this counter is safe until the year 2106. +* +* The number of blocks cannot be practically bigger than the number of seconds, since there is more than one second +* in a block. Thus, it is safe to assume that uint32 for the number of blocks is also sufficient. +* +* In conclusion, this contract is only safe to use until 2106. +*/ + +// The size of the struct is 96 + 32 * 2 = 160 (1 slot) +struct Bond { + // OLAS remaining to be paid out + // After 10 years, the OLAS inflation rate is 2% per year. It would take 220+ years to reach 2^96 - 1 + uint96 payout; + // Bond maturity time + // 2^32 - 1 is enough to count 136 years starting from the year of 1970. This counter is safe until the year of 2106 + uint32 maturity; + // Product Id of a bond + // We assume that the number of products will not be bigger than the number of seconds + uint32 productId; +} + +// The size of the struct is 160 + 96 + 160 + 96 + 32 = 2 * 256 + 32 (3 slots) +struct Product { + // priceLP (reserve0 / totalSupply or reserve1 / totalSupply) with 18 additional decimals + // priceLP = 2 * r0/L * 10^18 = 2*r0*10^18/sqrt(r0*r1) ~= 61 + 96 - sqrt(96 * 112) ~= 53 bits (if LP is balanced) + // or 2* r0/sqrt(r0) * 10^18 => 87 bits + 60 bits = 147 bits (if LP is unbalanced) + uint160 priceLP; + // Supply of remaining OLAS tokens + // After 10 years, the OLAS inflation rate is 2% per year. It would take 220+ years to reach 2^96 - 1 + uint96 supply; + // Token to accept as a payment + address token; + // Current OLAS payout + // This value is bound by the initial total supply + uint96 payout; + // Max bond vesting time + // 2^32 - 1 is enough to count 136 years starting from the year of 1970. This counter is safe until the year of 2106 + uint32 vesting; +} + +/// @title Bond Depository - Smart contract for OLAS Bond Depository +/// @author AL +/// @author Aleksandr Kuperman - +contract Depository is ERC721, IErrorsTokenomics { + event OwnerUpdated(address indexed owner); + event TokenomicsUpdated(address indexed tokenomics); + event TreasuryUpdated(address indexed treasury); + event BondCalculatorUpdated(address indexed bondCalculator); + event CreateBond(address indexed token, uint256 indexed productId, address indexed owner, uint256 bondId, + uint256 amountOLAS, uint256 tokenAmount, uint256 maturity); + event RedeemBond(uint256 indexed productId, address indexed owner, uint256 bondId, uint256 payout); + event CreateProduct(address indexed token, uint256 indexed productId, uint256 supply, uint256 priceLP, + uint256 vesting); + event CloseProduct(address indexed token, uint256 indexed productId, uint256 supply); + + // Minimum bond vesting value + uint256 public constant MIN_VESTING = 1 days; + // Depository version number + string public constant VERSION = "1.1.0"; + // Base URI + string public baseURI; + // Owner address + address public owner; + // Individual bond counter + // We assume that the number of bonds will not be bigger than the number of seconds + uint256 public totalSupply; + // Bond product counter + // We assume that the number of products will not be bigger than the number of seconds + uint256 public productCounter; + // Minimum amount of supply such that any value below is given to the bonding account in order to close the product + uint256 public minOLASLeftoverAmount; + + // OLAS token address + address public immutable olas; + // Tokenomics contract address + address public tokenomics; + // Treasury contract address + address public treasury; + // Bond Calculator contract address + address public bondCalculator; + + // Mapping of bond Id => account bond instance + mapping(uint256 => Bond) public mapUserBonds; + // Mapping of product Id => bond product instance + mapping(uint256 => Product) public mapBondProducts; + + /// @dev Depository constructor. + /// @param _name Service contract name. + /// @param _symbol Agent contract symbol. + /// @param _baseURI Agent registry token base URI. + /// @param _olas OLAS token address. + /// @param _treasury Treasury address. + /// @param _tokenomics Tokenomics address. + constructor( + string memory _name, + string memory _symbol, + string memory _baseURI, + address _olas, + address _tokenomics, + address _treasury, + address _bondCalculator + ) + ERC721(_name, _symbol) + { + // Check for at least one zero contract address + if (_olas == address(0) || _tokenomics == address(0) || _treasury == address(0) || _bondCalculator == address(0)) { + revert ZeroAddress(); + } + + // Check for base URI zero value + if (bytes(_baseURI).length == 0) { + revert ZeroValue(); + } + + olas = _olas; + tokenomics = _tokenomics; + treasury = _treasury; + bondCalculator = _bondCalculator; + baseURI = _baseURI; + owner = msg.sender; + } + + /// @dev Changes the owner address. + /// @param newOwner Address of a new owner. + /// #if_succeeds {:msg "Changing owner"} old(owner) == msg.sender ==> owner == newOwner; + function changeOwner(address newOwner) external { + // Check for the contract ownership + if (msg.sender != owner) { + revert OwnerOnly(msg.sender, owner); + } + + // Check for the zero address + if (newOwner == address(0)) { + revert ZeroAddress(); + } + + owner = newOwner; + emit OwnerUpdated(newOwner); + } + + /// @dev Changes various managing contract addresses. + /// @param _tokenomics Tokenomics address. + /// @param _treasury Treasury address. + /// #if_succeeds {:msg "tokenomics changed"} _tokenomics != address(0) ==> tokenomics == _tokenomics; + /// #if_succeeds {:msg "treasury changed"} _treasury != address(0) ==> treasury == _treasury; + function changeManagers(address _tokenomics, address _treasury) external { + // Check for the contract ownership + if (msg.sender != owner) { + revert OwnerOnly(msg.sender, owner); + } + + // Change Tokenomics contract address + if (_tokenomics != address(0)) { + tokenomics = _tokenomics; + emit TokenomicsUpdated(_tokenomics); + } + // Change Treasury contract address + if (_treasury != address(0)) { + treasury = _treasury; + emit TreasuryUpdated(_treasury); + } + } + + /// @dev Changes Bond Calculator contract address + /// #if_succeeds {:msg "bondCalculator changed"} _bondCalculator != address(0) ==> bondCalculator == _bondCalculator; + function changeBondCalculator(address _bondCalculator) external { + // Check for the contract ownership + if (msg.sender != owner) { + revert OwnerOnly(msg.sender, owner); + } + + if (_bondCalculator != address(0)) { + bondCalculator = _bondCalculator; + emit BondCalculatorUpdated(_bondCalculator); + } + } + + /// @dev Creates a new bond product. + /// @param token LP token to be deposited for pairs like OLAS-DAI, OLAS-ETH, etc. + /// @param priceLP LP token price with 18 additional decimals. + /// @param supply Supply in OLAS tokens. + /// @param vesting Vesting period (in seconds). + /// @return productId New bond product Id. + /// #if_succeeds {:msg "productCounter increases"} productCounter == old(productCounter) + 1; + /// #if_succeeds {:msg "isActive"} mapBondProducts[productId].supply > 0 && mapBondProducts[productId].vesting == vesting; + function create(address token, uint256 priceLP, uint256 supply, uint256 vesting) external returns (uint256 productId) { + // Check for the contract ownership + if (msg.sender != owner) { + revert OwnerOnly(msg.sender, owner); + } + + // Check for the pool liquidity as the LP price being greater than zero + if (priceLP == 0) { + revert ZeroValue(); + } + + // Check the priceLP limit value + if (priceLP > type(uint160).max) { + revert Overflow(priceLP, type(uint160).max); + } + + // Check that the supply is greater than zero + if (supply == 0) { + revert ZeroValue(); + } + + // Check the supply limit value + if (supply > type(uint96).max) { + revert Overflow(supply, type(uint96).max); + } + + // Check the vesting minimum limit value + if (vesting < MIN_VESTING) { + revert LowerThan(vesting, MIN_VESTING); + } + + // Check for the maturity time overflow for the current timestamp + uint256 maturity = block.timestamp + vesting; + if (maturity > type(uint32).max) { + revert Overflow(maturity, type(uint32).max); + } + + // Check if the LP token is enabled + if (!ITreasury(treasury).isEnabled(token)) { + revert UnauthorizedToken(token); + } + + // Check if the bond amount is beyond the limits + if (!ITokenomics(tokenomics).reserveAmountForBondProgram(supply)) { + revert LowerThan(ITokenomics(tokenomics).effectiveBond(), supply); + } + + // Push newly created bond product into the list of products + productId = productCounter; + mapBondProducts[productId] = Product(uint160(priceLP), uint96(supply), token, 0, uint32(vesting)); + // Even if we create a bond product every second, 2^32 - 1 is enough for the next 136 years + productCounter = productId + 1; + emit CreateProduct(token, productId, supply, priceLP, vesting); + } + + /// @dev Closes bonding products. + /// @notice This will terminate programs regardless of their vesting time. + /// @param productIds Set of product Ids. + /// @return closedProductIds Set of closed product Ids. + /// #if_succeeds {:msg "productCounter not touched"} productCounter == old(productCounter); + /// #if_succeeds {:msg "success closed"} forall (uint k in productIds) mapBondProducts[productIds[k]].vesting == 0 && mapBondProducts[productIds[k]].supply == 0; + function close(uint256[] memory productIds) external returns (uint256[] memory closedProductIds) { + // Check for the contract ownership + if (msg.sender != owner) { + revert OwnerOnly(msg.sender, owner); + } + + // Calculate the number of closed products + uint256 numProducts = productIds.length; + uint256[] memory ids = new uint256[](numProducts); + uint256 numClosedProducts; + // Traverse to close all possible products + for (uint256 i = 0; i < numProducts; ++i) { + uint256 productId = productIds[i]; + // Check if the product is still open by getting its supply amount + uint256 supply = mapBondProducts[productId].supply; + // The supply is greater than zero only if the product is active, otherwise it is already closed + if (supply > 0) { + // Refund unused OLAS supply from the product if it was not used by the product completely + ITokenomics(tokenomics).refundFromBondProgram(supply); + address token = mapBondProducts[productId].token; + delete mapBondProducts[productId]; + + ids[numClosedProducts] = productIds[i]; + ++numClosedProducts; + emit CloseProduct(token, productId, supply); + } + } + + // Get the correct array size of closed product Ids + closedProductIds = new uint256[](numClosedProducts); + for (uint256 i = 0; i < numClosedProducts; ++i) { + closedProductIds[i] = ids[i]; + } + } + + /// @dev Deposits tokens in exchange for a bond from a specified product. + /// @param productId Product Id. + /// @param tokenAmount Token amount to deposit for the bond. + /// @return payout The amount of OLAS tokens due. + /// @return maturity Timestamp for payout redemption. + /// @return bondId Id of a newly created bond. + /// #if_succeeds {:msg "token is valid"} mapBondProducts[productId].token != address(0); + /// #if_succeeds {:msg "input supply is non-zero"} old(mapBondProducts[productId].supply) > 0 && mapBondProducts[productId].supply <= type(uint96).max; + /// #if_succeeds {:msg "vesting is non-zero"} mapBondProducts[productId].vesting > 0 && mapBondProducts[productId].vesting + block.timestamp <= type(uint32).max; + /// #if_succeeds {:msg "bond Id"} totalSupply == old(totalSupply) + 1 && totalSupply <= type(uint32).max; + /// #if_succeeds {:msg "payout"} old(mapBondProducts[productId].supply) == mapBondProducts[productId].supply + payout; + /// #if_succeeds {:msg "OLAS balances"} IToken(mapBondProducts[productId].token).balanceOf(treasury) == old(IToken(mapBondProducts[productId].token).balanceOf(treasury)) + tokenAmount; + function deposit(uint256 productId, uint256 tokenAmount, uint256 bondVestingTime) external + returns (uint256 payout, uint256 maturity, uint256 bondId) + { + // Check the token amount + if (tokenAmount == 0) { + revert ZeroValue(); + } + + // Get the bonding product + Product storage product = mapBondProducts[productId]; + + // Check for the product supply, which is zero if the product was closed or never existed + uint256 supply = product.supply; + if (supply == 0) { + revert ProductClosed(productId); + } + + uint256 productMaxVestingTime = product.vesting; + // Calculate vesting limits + if (bondVestingTime < MIN_VESTING) { + revert LowerThan(bondVestingTime, MIN_VESTING); + } + if (bondVestingTime > productMaxVestingTime) { + revert Overflow(bondVestingTime, productMaxVestingTime); + } + // Calculate the bond maturity based on its vesting time + maturity = block.timestamp + bondVestingTime; + // Check for the time limits + if (maturity > type(uint32).max) { + revert Overflow(maturity, type(uint32).max); + } + + // Get the LP token address + address token = product.token; + + // Calculate the payout in OLAS tokens based on the LP pair with the inverse discount factor (IDF) calculation + // Note that payout cannot be zero since the price LP is non-zero, otherwise the product would not be created + payout = IBondCalculator(bondCalculator).calculatePayoutOLAS(msg.sender, tokenAmount, product.priceLP, + bondVestingTime, productMaxVestingTime, supply, product.payout); + + // Check for the sufficient supply + if (payout > supply) { + revert ProductSupplyLow(token, productId, payout, supply); + } + + // Decrease the supply for the amount of payout + supply -= payout; + // Adjust payout and set supply to zero if supply drops below the min defined value + if (supply < minOLASLeftoverAmount) { + payout += supply; + supply = 0; + } + product.supply = uint96(supply); + product.payout += uint96(payout); + + // Create and mint a new bond + bondId = totalSupply; + // Safe mint is needed since contracts can create bonds as well + _safeMint(msg.sender, bondId); + mapUserBonds[bondId] = Bond(uint96(payout), uint32(maturity), uint32(productId)); + + // Increase bond total supply + totalSupply = bondId + 1; + + uint256 olasBalance = IToken(olas).balanceOf(address(this)); + // Deposit that token amount to mint OLAS tokens in exchange + ITreasury(treasury).depositTokenForOLAS(msg.sender, tokenAmount, token, payout); + + // Check the balance after the OLAS mint + olasBalance = IToken(olas).balanceOf(address(this)) - olasBalance; + + if (olasBalance != payout) { + revert WrongAmount(olasBalance, payout); + } + + // Close the product if the supply becomes zero + if (supply == 0) { + delete mapBondProducts[productId]; + emit CloseProduct(token, productId, supply); + } + + emit CreateBond(token, productId, msg.sender, bondId, payout, tokenAmount, maturity); + } + + /// @dev Redeems account bonds. + /// @param bondIds Bond Ids to redeem. + /// @return payout Total payout sent in OLAS tokens. + /// #if_succeeds {:msg "payout > 0"} payout > 0; + /// #if_succeeds {:msg "msg.sender is the only owner"} old(forall (uint k in bondIds) _ownerOf[bondIds[k]] == msg.sender); + /// #if_succeeds {:msg "accounts deleted"} forall (uint k in bondIds) _ownerOf[bondIds[k]].account == address(0); + /// #if_succeeds {:msg "payouts are zeroed"} forall (uint k in bondIds) mapUserBonds[bondIds[k]].payout == 0; + /// #if_succeeds {:msg "maturities are zeroed"} forall (uint k in bondIds) mapUserBonds[bondIds[k]].maturity == 0; + function redeem(uint256[] memory bondIds) external returns (uint256 payout) { + for (uint256 i = 0; i < bondIds.length; ++i) { + // Get the amount to pay and the maturity status + uint256 pay = mapUserBonds[bondIds[i]].payout; + bool matured = block.timestamp >= mapUserBonds[bondIds[i]].maturity; + + // Revert if the bond does not exist or is not matured yet + if (pay == 0 || !matured) { + revert BondNotRedeemable(bondIds[i]); + } + + // Check that the msg.sender is the owner of the bond + address bondOwner = _ownerOf[bondIds[i]]; + if (bondOwner != msg.sender) { + revert OwnerOnly(msg.sender, bondOwner); + } + + // Increase the payout + payout += pay; + + // Get the productId + uint256 productId = mapUserBonds[bondIds[i]].productId; + + // Burn the bond NFT + _burn(bondIds[i]); + + // Delete the Bond struct and release the gas + delete mapUserBonds[bondIds[i]]; + emit RedeemBond(productId, msg.sender, bondIds[i], pay); + } + + // Check for the non-zero payout + if (payout == 0) { + revert ZeroValue(); + } + + // No reentrancy risk here since it's the last operation, and originated from the OLAS token + // No need to check for the return value, since it either reverts or returns true, see the ERC20 implementation + IToken(olas).transfer(msg.sender, payout); + } + + /// @dev Gets an array of active or inactive product Ids. + /// @param active Flag to select active or inactive products. + /// @return productIds Product Ids. + function getProducts(bool active) external view returns (uint256[] memory productIds) { + // Calculate the number of existing products + uint256 numProducts = productCounter; + bool[] memory positions = new bool[](numProducts); + uint256 numSelectedProducts; + // Traverse to find requested products + for (uint256 i = 0; i < numProducts; ++i) { + // Product is always active if its supply is not zero, and inactive otherwise + if ((active && mapBondProducts[i].supply > 0) || (!active && mapBondProducts[i].supply == 0)) { + positions[i] = true; + ++numSelectedProducts; + } + } + + // Form active or inactive products index array + productIds = new uint256[](numSelectedProducts); + uint256 numPos; + for (uint256 i = 0; i < numProducts; ++i) { + if (positions[i]) { + productIds[numPos] = i; + ++numPos; + } + } + } + + /// @dev Gets activity information about a given product. + /// @param productId Product Id. + /// @return status True if the product is active. + function isActiveProduct(uint256 productId) external view returns (bool status) { + status = (mapBondProducts[productId].supply > 0); + } + + /// @dev Gets bond Ids for the account address. + /// @param account Account address to query bonds for. + /// @param matured Flag to get matured bonds only or all of them. + /// @return bondIds Bond Ids. + /// @return payout Cumulative expected OLAS payout. + /// #if_succeeds {:msg "matured bonds"} matured == true ==> forall (uint k in bondIds) + /// mapUserBonds[bondIds[k]].account == account && block.timestamp >= mapUserBonds[bondIds[k]].maturity; + function getBonds(address account, bool matured) external view + returns (uint256[] memory bondIds, uint256 payout) + { + // Check the address + if (account == address(0)) { + revert ZeroAddress(); + } + + uint256 numAccountBonds; + // Calculate the number of pending bonds + uint256 numBonds = totalSupply; + bool[] memory positions = new bool[](numBonds); + // Record the bond number if it belongs to the account address and was not yet redeemed + for (uint256 i = 0; i < numBonds; ++i) { + // Check if the bond belongs to the account + // If not and the address is zero, the bond was redeemed or never existed + if (_ownerOf[i] == account) { + // Check if requested bond is not matured but owned by the account address + if (!matured || + // Or if the requested bond is matured, i.e., the bond maturity timestamp passed + block.timestamp >= mapUserBonds[i].maturity) + { + positions[i] = true; + ++numAccountBonds; + // The payout is always bigger than zero if the bond exists + payout += mapUserBonds[i].payout; + } + } + } + + // Form pending bonds index array + bondIds = new uint256[](numAccountBonds); + uint256 numPos; + for (uint256 i = 0; i < numBonds; ++i) { + if (positions[i]) { + bondIds[numPos] = i; + ++numPos; + } + } + } + + /// @dev Calculates the maturity and payout to claim for a single bond. + /// @param bondId The account bond Id. + /// @return payout The payout amount in OLAS. + /// @return matured True if the payout can be redeemed. + function getBondStatus(uint256 bondId) external view returns (uint256 payout, bool matured) { + payout = mapUserBonds[bondId].payout; + // If payout is zero, the bond has been redeemed or never existed + if (payout > 0) { + matured = block.timestamp >= mapUserBonds[bondId].maturity; + } + } + + /// @dev Gets current reserves of OLAS / totalSupply of Uniswap L2-like LP tokens. + /// @param token Token address. + /// @return priceLP Resulting reserveX / totalSupply ratio with 18 decimals. + function getCurrentPriceLP(address token) external view returns (uint256 priceLP) { + return IBondCalculator(bondCalculator).getCurrentPriceLP(token); + } + + /// @dev Gets the valid bond Id from the provided index. + /// @param id Bond counter. + /// @return Bond Id. + function tokenByIndex(uint256 id) external view returns (uint256) { + if (id >= totalSupply) { + revert Overflow(id, totalSupply - 1); + } + + return id; + } + + /// @dev Returns bond token URI. + /// @param bondId Bond Id. + /// @return Bond token URI string. + function tokenURI(uint256 bondId) public view override returns (string memory) { + return string(abi.encodePacked(baseURI, bondId)); + } +} diff --git a/audits/internal6/analysis/contracts/script.sh b/audits/internal6/analysis/contracts/script.sh new file mode 100755 index 00000000..286784b4 --- /dev/null +++ b/audits/internal6/analysis/contracts/script.sh @@ -0,0 +1,20 @@ +#!/bin/bash + + slither_options=("call-graph" "constructor-calls" "contract-summary" "data-dependency" "function-summary" + "human-summary" "inheritance" "inheritance-graph" "modifiers" "require" "variable-order" "vars-and-auth") + echo -e "\nRunning slither routines ..." + for so in "${slither_options[@]}"; do + echo -e "\t$so" + slither . --print ${so} &> "slither_$so.txt" + done + echo -e "\tfull report" + slither . &> "slither_full.txt" + + # moving generated .dot files to the audit folder + count=`ls -1 *.dot 2>/dev/null | wc -l` + echo -e "\tgenerated $count .dot files" + for _filename in *.dot; do + filename="${_filename%.*}" + cat $_filename | dot -Tpng > slither_$filename.png + done + rm *.dot diff --git a/audits/internal6/analysis/slither_BondCalculator-flatten.sol.BondCalculator.call-graph.png b/audits/internal6/analysis/slither_BondCalculator-flatten.sol.BondCalculator.call-graph.png new file mode 100644 index 00000000..bd46abc6 Binary files /dev/null and b/audits/internal6/analysis/slither_BondCalculator-flatten.sol.BondCalculator.call-graph.png differ diff --git a/audits/internal6/analysis/slither_BondCalculator-flatten.sol.ITokenomics.call-graph.png b/audits/internal6/analysis/slither_BondCalculator-flatten.sol.ITokenomics.call-graph.png new file mode 100644 index 00000000..f522a0ee Binary files /dev/null and b/audits/internal6/analysis/slither_BondCalculator-flatten.sol.ITokenomics.call-graph.png differ diff --git a/audits/internal6/analysis/slither_BondCalculator-flatten.sol.IUniswapV2Pair.call-graph.png b/audits/internal6/analysis/slither_BondCalculator-flatten.sol.IUniswapV2Pair.call-graph.png new file mode 100644 index 00000000..f9b1ed3a Binary files /dev/null and b/audits/internal6/analysis/slither_BondCalculator-flatten.sol.IUniswapV2Pair.call-graph.png differ diff --git a/audits/internal6/analysis/slither_BondCalculator-flatten.sol.IVotingEscrow.call-graph.png b/audits/internal6/analysis/slither_BondCalculator-flatten.sol.IVotingEscrow.call-graph.png new file mode 100644 index 00000000..fdaa8b9a Binary files /dev/null and b/audits/internal6/analysis/slither_BondCalculator-flatten.sol.IVotingEscrow.call-graph.png differ diff --git a/audits/internal6/analysis/slither_BondCalculator-flatten.sol.all_contracts.call-graph.png b/audits/internal6/analysis/slither_BondCalculator-flatten.sol.all_contracts.call-graph.png new file mode 100644 index 00000000..273f01c8 Binary files /dev/null and b/audits/internal6/analysis/slither_BondCalculator-flatten.sol.all_contracts.call-graph.png differ diff --git a/audits/internal6/analysis/slither_BondCalculator-flatten.sol.inheritance-graph.png b/audits/internal6/analysis/slither_BondCalculator-flatten.sol.inheritance-graph.png new file mode 100644 index 00000000..82ab2167 Binary files /dev/null and b/audits/internal6/analysis/slither_BondCalculator-flatten.sol.inheritance-graph.png differ diff --git a/audits/internal6/analysis/slither_Depository-flatten.sol.Depository.call-graph.png b/audits/internal6/analysis/slither_Depository-flatten.sol.Depository.call-graph.png new file mode 100644 index 00000000..8667c8d6 Binary files /dev/null and b/audits/internal6/analysis/slither_Depository-flatten.sol.Depository.call-graph.png differ diff --git a/audits/internal6/analysis/slither_Depository-flatten.sol.ERC721TokenReceiver.call-graph.png b/audits/internal6/analysis/slither_Depository-flatten.sol.ERC721TokenReceiver.call-graph.png new file mode 100644 index 00000000..70f08c24 Binary files /dev/null and b/audits/internal6/analysis/slither_Depository-flatten.sol.ERC721TokenReceiver.call-graph.png differ diff --git a/audits/internal6/analysis/slither_Depository-flatten.sol.IBondCalculator.call-graph.png b/audits/internal6/analysis/slither_Depository-flatten.sol.IBondCalculator.call-graph.png new file mode 100644 index 00000000..ff462e90 Binary files /dev/null and b/audits/internal6/analysis/slither_Depository-flatten.sol.IBondCalculator.call-graph.png differ diff --git a/audits/internal6/analysis/slither_Depository-flatten.sol.IToken.call-graph.png b/audits/internal6/analysis/slither_Depository-flatten.sol.IToken.call-graph.png new file mode 100644 index 00000000..44c9bda8 Binary files /dev/null and b/audits/internal6/analysis/slither_Depository-flatten.sol.IToken.call-graph.png differ diff --git a/audits/internal6/analysis/slither_Depository-flatten.sol.ITokenomics.call-graph.png b/audits/internal6/analysis/slither_Depository-flatten.sol.ITokenomics.call-graph.png new file mode 100644 index 00000000..407c3c7e Binary files /dev/null and b/audits/internal6/analysis/slither_Depository-flatten.sol.ITokenomics.call-graph.png differ diff --git a/audits/internal6/analysis/slither_Depository-flatten.sol.ITreasury.call-graph.png b/audits/internal6/analysis/slither_Depository-flatten.sol.ITreasury.call-graph.png new file mode 100644 index 00000000..600bad7c Binary files /dev/null and b/audits/internal6/analysis/slither_Depository-flatten.sol.ITreasury.call-graph.png differ diff --git a/audits/internal6/analysis/slither_Depository-flatten.sol.all_contracts.call-graph.png b/audits/internal6/analysis/slither_Depository-flatten.sol.all_contracts.call-graph.png new file mode 100644 index 00000000..d0354775 Binary files /dev/null and b/audits/internal6/analysis/slither_Depository-flatten.sol.all_contracts.call-graph.png differ diff --git a/audits/internal6/analysis/slither_Depository-flatten.sol.inheritance-graph.png b/audits/internal6/analysis/slither_Depository-flatten.sol.inheritance-graph.png new file mode 100644 index 00000000..bd66ae9c Binary files /dev/null and b/audits/internal6/analysis/slither_Depository-flatten.sol.inheritance-graph.png differ diff --git a/audits/internal6/analysis/slither_call-graph.txt b/audits/internal6/analysis/slither_call-graph.txt new file mode 100644 index 00000000..6b424beb --- /dev/null +++ b/audits/internal6/analysis/slither_call-graph.txt @@ -0,0 +1,32 @@ +'solc --version' running +'solc ./BondCalculator-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +'solc --version' running +'solc ./Depository-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +Compilation warnings/errors on ./Depository-flatten.sol: +Warning: This declaration shadows an existing declaration. + --> Depository-flatten.sol:84:5: + | +84 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Note: The shadowed declaration is here: + --> Depository-flatten.sol:528:1: + | +528 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +INFO:Printers:Call Graph: ./BondCalculator-flatten.sol.all_contracts.call-graph.dot +Call Graph: ./BondCalculator-flatten.sol.IUniswapV2Pair.call-graph.dot +Call Graph: ./BondCalculator-flatten.sol.IVotingEscrow.call-graph.dot +Call Graph: ./BondCalculator-flatten.sol.ITokenomics.call-graph.dot +Call Graph: ./BondCalculator-flatten.sol.BondCalculator.call-graph.dot + +INFO:Printers:Call Graph: ./Depository-flatten.sol.all_contracts.call-graph.dot +Call Graph: ./Depository-flatten.sol.IToken.call-graph.dot +Call Graph: ./Depository-flatten.sol.ITokenomics.call-graph.dot +Call Graph: ./Depository-flatten.sol.ITreasury.call-graph.dot +Call Graph: ./Depository-flatten.sol.ERC721TokenReceiver.call-graph.dot +Call Graph: ./Depository-flatten.sol.IBondCalculator.call-graph.dot +Call Graph: ./Depository-flatten.sol.Depository.call-graph.dot + +INFO:Slither:. analyzed (12 contracts) diff --git a/audits/internal6/analysis/slither_constructor-calls.txt b/audits/internal6/analysis/slither_constructor-calls.txt new file mode 100644 index 00000000..798dc6fb --- /dev/null +++ b/audits/internal6/analysis/slither_constructor-calls.txt @@ -0,0 +1,107 @@ +'solc --version' running +'solc ./BondCalculator-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +'solc --version' running +'solc ./Depository-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +Compilation warnings/errors on ./Depository-flatten.sol: +Warning: This declaration shadows an existing declaration. + --> Depository-flatten.sol:84:5: + | +84 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Note: The shadowed declaration is here: + --> Depository-flatten.sol:528:1: + | +528 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +INFO:Printers: +############################## +####### BondCalculator ####### +############################## + +## Constructor Call Sequence + - BondCalculator + +## Constructor Definitions + +### BondCalculator + + tructor(address _olas, address _tokenomics, address _ve, DiscountParams memory _discountParams) { + // Check for at least one zero contract address + if (_olas == address(0) || _tokenomics == address(0) || _ve == address(0)) { + revert ZeroAddress(); + } + + olas = _olas; + tokenomics = _tokenomics; + ve = _ve; + owner = msg.sender; + + // Check for zero values + if (_discountParams.targetNewUnits == 0 || _discountParams.targetVotingPower == 0) { + revert ZeroValue(); + } + // Check the sum of factors that cannot exceed the value of 10_000 (100% with a 0.01% step) + uint256 sumWeights; + for (uint256 i = 0; i < _discountParams.weightFactors.length; ++i) { + sumWeights += _discountParams.weightFactors[i]; + } + if (sumWeights > MAX_SUM_WEIGHTS) { + revert Overflow(sumWeights, MAX_SUM_WEIGHTS); + } + discountParams = _discountParams; + } + + + +INFO:Printers: +########################## +####### Depository ####### +########################## + +## Constructor Call Sequence + - ERC721 + - Depository + +## Constructor Definitions + +### ERC721 + + constructor(string memory _name, string memory _symbol) { + name = _name; + symbol = _symbol; + } + +### Depository + + constructor( + string memory _name, + string memory _symbol, + string memory _baseURI, + address _olas, + address _tokenomics, + address _treasury, + address _bondCalculator + ) + ERC721(_name, _symbol) + { + // Check for at least one zero contract address + if (_olas == address(0) || _tokenomics == address(0) || _treasury == address(0) || _bondCalculator == address(0)) { + revert ZeroAddress(); + } + + // Check for base URI zero value + if (bytes(_baseURI).length == 0) { + revert ZeroValue(); + } + + olas = _olas; + tokenomics = _tokenomics; + treasury = _treasury; + bondCalculator = _bondCalculator; + baseURI = _baseURI; + owner = msg.sender; + } + +INFO:Slither:. analyzed (12 contracts) diff --git a/audits/internal6/analysis/slither_contract-summary.txt b/audits/internal6/analysis/slither_contract-summary.txt new file mode 100644 index 00000000..25d9cec0 --- /dev/null +++ b/audits/internal6/analysis/slither_contract-summary.txt @@ -0,0 +1,134 @@ +'solc --version' running +'solc ./BondCalculator-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +'solc --version' running +'solc ./Depository-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +Compilation warnings/errors on ./Depository-flatten.sol: +Warning: This declaration shadows an existing declaration. + --> Depository-flatten.sol:84:5: + | +84 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Note: The shadowed declaration is here: + --> Depository-flatten.sol:528:1: + | +528 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +INFO:Printers: ++ Contract IUniswapV2Pair (Most derived contract) + - From IUniswapV2Pair + - getReserves() (external) + - token0() (external) + - token1() (external) + - totalSupply() (external) + ++ Contract IVotingEscrow (Most derived contract) + - From IVotingEscrow + - getVotes(address) (external) + ++ Contract ITokenomics (Most derived contract) + - From ITokenomics + - getLastEpochNumNewUnits() (external) + ++ Contract BondCalculator (Most derived contract) + - From BondCalculator + - calculateIDF(address,uint256,uint256,uint256,uint256) (public) + - calculatePayoutOLAS(address,uint256,uint256,uint256,uint256,uint256,uint256) (external) + - changeDiscountParams(DiscountParams) (external) + - changeOwner(address) (external) + - constructor(address,address,address,DiscountParams) (public) + - getCurrentPriceLP(address) (external) + - getDiscountParams() (external) + +INFO:Printers: ++ Contract IErrorsTokenomics + ++ Contract IToken (Most derived contract) + - From IToken + - allowance(address,address) (external) + - approve(address,uint256) (external) + - balanceOf(address) (external) + - ownerOf(uint256) (external) + - totalSupply() (external) + - transfer(address,uint256) (external) + - transferFrom(address,address,uint256) (external) + ++ Contract ITokenomics (Most derived contract) + - From ITokenomics + - accountOwnerIncentives(address,uint256[],uint256[]) (external) + - checkpoint() (external) + - effectiveBond() (external) + - getLastIDF() (external) + - refundFromBondProgram(uint256) (external) + - reserveAmountForBondProgram(uint256) (external) + - serviceRegistry() (external) + - trackServiceDonations(address,uint256[],uint256[],uint256) (external) + ++ Contract ITreasury (Most derived contract) + - From ITreasury + - depositServiceDonationsETH(uint256[],uint256[]) (external) + - depositTokenForOLAS(address,uint256,address,uint256) (external) + - isEnabled(address) (external) + - rebalanceTreasury(uint256) (external) + - withdrawToAccount(address,uint256,uint256) (external) + ++ Contract ERC721 + - From ERC721 + - _burn(uint256) (internal) + - _mint(address,uint256) (internal) + - _safeMint(address,uint256) (internal) + - _safeMint(address,uint256,bytes) (internal) + - approve(address,uint256) (public) + - balanceOf(address) (public) + - constructor(string,string) (internal) + - ownerOf(uint256) (public) + - safeTransferFrom(address,address,uint256) (public) + - safeTransferFrom(address,address,uint256,bytes) (public) + - setApprovalForAll(address,bool) (public) + - supportsInterface(bytes4) (public) + - tokenURI(uint256) (public) + - transferFrom(address,address,uint256) (public) + ++ Contract ERC721TokenReceiver (Most derived contract) + - From ERC721TokenReceiver + - onERC721Received(address,address,uint256,bytes) (external) + ++ Contract IBondCalculator (Most derived contract) + - From IBondCalculator + - calculatePayoutOLAS(address,uint256,uint256,uint256,uint256,uint256,uint256) (external) + - getCurrentPriceLP(address) (external) + ++ Contract Depository (Most derived contract) + - From ERC721 + - _burn(uint256) (internal) + - _mint(address,uint256) (internal) + - _safeMint(address,uint256) (internal) + - _safeMint(address,uint256,bytes) (internal) + - approve(address,uint256) (public) + - balanceOf(address) (public) + - constructor(string,string) (internal) + - ownerOf(uint256) (public) + - safeTransferFrom(address,address,uint256) (public) + - safeTransferFrom(address,address,uint256,bytes) (public) + - setApprovalForAll(address,bool) (public) + - supportsInterface(bytes4) (public) + - transferFrom(address,address,uint256) (public) + - From Depository + - changeBondCalculator(address) (external) + - changeManagers(address,address) (external) + - changeOwner(address) (external) + - close(uint256[]) (external) + - constructor(string,string,string,address,address,address,address) (public) + - create(address,uint256,uint256,uint256) (external) + - deposit(uint256,uint256,uint256) (external) + - getBondStatus(uint256) (external) + - getBonds(address,bool) (external) + - getCurrentPriceLP(address) (external) + - getProducts(bool) (external) + - isActiveProduct(uint256) (external) + - redeem(uint256[]) (external) + - tokenByIndex(uint256) (external) + - tokenURI(uint256) (public) + +INFO:Slither:. analyzed (12 contracts) diff --git a/audits/internal6/analysis/slither_data-dependency.txt b/audits/internal6/analysis/slither_data-dependency.txt new file mode 100644 index 00000000..fd3fc7ca --- /dev/null +++ b/audits/internal6/analysis/slither_data-dependency.txt @@ -0,0 +1,2789 @@ +'solc --version' running +'solc ./BondCalculator-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +'solc --version' running +'solc ./Depository-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +Compilation warnings/errors on ./Depository-flatten.sol: +Warning: This declaration shadows an existing declaration. + --> Depository-flatten.sol:84:5: + | +84 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Note: The shadowed declaration is here: + --> Depository-flatten.sol:528:1: + | +528 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +INFO:Printers: +Contract IUniswapV2Pair ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function totalSupply() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function token0() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function token1() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function getReserves() ++--------------------+--------------+ +| Variable | Dependencies | ++--------------------+--------------+ +| reserve0 | [] | +| reserve1 | [] | +| blockTimestampLast | [] | ++--------------------+--------------+ +INFO:Printers: +Contract IUniswapV2Pair ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function totalSupply() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function token0() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function token1() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function getReserves() ++--------------------+--------------+ +| Variable | Dependencies | ++--------------------+--------------+ +| reserve0 | [] | +| reserve1 | [] | +| blockTimestampLast | [] | ++--------------------+--------------+ +Contract IVotingEscrow ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function getVotes(address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| account | [] | +| | [] | ++----------+--------------+ +INFO:Printers: +Contract IUniswapV2Pair ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function totalSupply() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function token0() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function token1() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function getReserves() ++--------------------+--------------+ +| Variable | Dependencies | ++--------------------+--------------+ +| reserve0 | [] | +| reserve1 | [] | +| blockTimestampLast | [] | ++--------------------+--------------+ +Contract IVotingEscrow ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function getVotes(address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| account | [] | +| | [] | ++----------+--------------+ +Contract ITokenomics ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function getLastEpochNumNewUnits() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +INFO:Printers: +Contract IUniswapV2Pair ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function totalSupply() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function token0() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function token1() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function getReserves() ++--------------------+--------------+ +| Variable | Dependencies | ++--------------------+--------------+ +| reserve0 | [] | +| reserve1 | [] | +| blockTimestampLast | [] | ++--------------------+--------------+ +Contract IVotingEscrow ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function getVotes(address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| account | [] | +| | [] | ++----------+--------------+ +Contract ITokenomics ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function getLastEpochNumNewUnits() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Contract BondCalculator ++-----------------+------------------------------------------------------------+ +| Variable | Dependencies | ++-----------------+------------------------------------------------------------+ +| MAX_SUM_WEIGHTS | ['MAX_SUM_WEIGHTS'] | +| olas | ['_olas', 'olas'] | +| tokenomics | ['_tokenomics', 'tokenomics'] | +| ve | ['_ve', 've'] | +| owner | ['msg.sender', 'newOwner', 'owner'] | +| discountParams | ['_discountParams', 'discountParams', 'newDiscountParams'] | ++-----------------+------------------------------------------------------------+ + +Function constructor(address,address,address,DiscountParams) ++--------------------------------+-----------------------------------+ +| Variable | Dependencies | ++--------------------------------+-----------------------------------+ +| _olas | [] | +| _tokenomics | [] | +| _ve | [] | +| _discountParams | ['_discountParams'] | +| sumWeights | ['_discountParams', 'sumWeights'] | +| i | ['i'] | +| BondCalculator.MAX_SUM_WEIGHTS | ['MAX_SUM_WEIGHTS'] | +| BondCalculator.olas | ['_olas'] | +| BondCalculator.tokenomics | ['_tokenomics'] | +| BondCalculator.ve | ['_ve'] | +| BondCalculator.owner | ['msg.sender'] | +| BondCalculator.discountParams | ['_discountParams'] | ++--------------------------------+-----------------------------------+ +Function changeOwner(address) ++--------------------------------+-----------------------+ +| Variable | Dependencies | ++--------------------------------+-----------------------+ +| newOwner | [] | +| BondCalculator.MAX_SUM_WEIGHTS | [] | +| BondCalculator.olas | [] | +| BondCalculator.tokenomics | [] | +| BondCalculator.ve | [] | +| BondCalculator.owner | ['newOwner', 'owner'] | +| BondCalculator.discountParams | [] | ++--------------------------------+-----------------------+ +Function changeDiscountParams(DiscountParams) ++--------------------------------+-------------------------------------+ +| Variable | Dependencies | ++--------------------------------+-------------------------------------+ +| newDiscountParams | ['newDiscountParams'] | +| sumWeights | ['newDiscountParams', 'sumWeights'] | +| i | ['i'] | +| BondCalculator.MAX_SUM_WEIGHTS | ['MAX_SUM_WEIGHTS'] | +| BondCalculator.olas | [] | +| BondCalculator.tokenomics | [] | +| BondCalculator.ve | [] | +| BondCalculator.owner | ['owner'] | +| BondCalculator.discountParams | ['newDiscountParams'] | ++--------------------------------+-------------------------------------+ +Function calculateIDF(address,uint256,uint256,uint256,uint256) ++--------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Variable | Dependencies | ++--------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| account | ['account'] | +| bondVestingTime | ['bondVestingTime'] | +| productMaxVestingTime | ['productMaxVestingTime'] | +| productSupply | ['productPayout', 'productSupply'] | +| productPayout | ['productPayout'] | +| idf | ['MAX_SUM_WEIGHTS', 'account', 'bondVestingTime', 'discountBooster', 'discountParams', 'localParams', 'numNewUnits', 'productMaxVestingTime', 'productPayout', 'productSupply', 'tokenomics', 'vPower', 've'] | +| localParams | ['discountParams', 'localParams'] | +| discountBooster | ['MAX_SUM_WEIGHTS', 'account', 'bondVestingTime', 'discountBooster', 'discountParams', 'localParams', 'numNewUnits', 'productMaxVestingTime', 'productPayout', 'productSupply', 'tokenomics', 'vPower', 've'] | +| numNewUnits | ['tokenomics'] | +| vPower | ['account', 've'] | +| BondCalculator.MAX_SUM_WEIGHTS | ['MAX_SUM_WEIGHTS'] | +| BondCalculator.olas | [] | +| BondCalculator.tokenomics | ['tokenomics'] | +| BondCalculator.ve | ['ve'] | +| BondCalculator.owner | [] | +| BondCalculator.discountParams | ['discountParams'] | ++--------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +Function calculatePayoutOLAS(address,uint256,uint256,uint256,uint256,uint256,uint256) ++--------------------------------+----------------------------+ +| Variable | Dependencies | ++--------------------------------+----------------------------+ +| account | [] | +| tokenAmount | [] | +| priceLP | [] | +| bondVestingTime | [] | +| productMaxVestingTime | [] | +| productSupply | [] | +| productPayout | [] | +| amountOLAS | ['idf', 'totalTokenValue'] | +| totalTokenValue | [] | +| idf | [] | +| BondCalculator.MAX_SUM_WEIGHTS | [] | +| BondCalculator.olas | [] | +| BondCalculator.tokenomics | [] | +| BondCalculator.ve | [] | +| BondCalculator.owner | [] | +| BondCalculator.discountParams | [] | ++--------------------------------+----------------------------+ +Function getCurrentPriceLP(address) ++--------------------------------+---------------------------------------------------------------------+ +| Variable | Dependencies | ++--------------------------------+---------------------------------------------------------------------+ +| token | [] | +| priceLP | ['TUPLE_0', 'pair', 'reserve0', 'reserve1', 'token', 'totalSupply'] | +| pair | ['token'] | +| totalSupply | ['pair', 'token'] | +| token0 | ['pair', 'token'] | +| token1 | ['pair', 'token'] | +| reserve0 | ['TUPLE_0', 'pair', 'token'] | +| reserve1 | ['TUPLE_0', 'pair', 'reserve0', 'reserve1', 'token'] | +| BondCalculator.MAX_SUM_WEIGHTS | [] | +| BondCalculator.olas | ['olas'] | +| BondCalculator.tokenomics | [] | +| BondCalculator.ve | [] | +| BondCalculator.owner | [] | +| BondCalculator.discountParams | [] | ++--------------------------------+---------------------------------------------------------------------+ +Function getDiscountParams() ++--------------------------------+--------------------+ +| Variable | Dependencies | ++--------------------------------+--------------------+ +| | [] | +| BondCalculator.MAX_SUM_WEIGHTS | [] | +| BondCalculator.olas | [] | +| BondCalculator.tokenomics | [] | +| BondCalculator.ve | [] | +| BondCalculator.owner | [] | +| BondCalculator.discountParams | ['discountParams'] | ++--------------------------------+--------------------+ +Function slitherConstructorConstantVariables() ++--------------------------------+--------------+ +| Variable | Dependencies | ++--------------------------------+--------------+ +| BondCalculator.MAX_SUM_WEIGHTS | [] | +| BondCalculator.olas | [] | +| BondCalculator.tokenomics | [] | +| BondCalculator.ve | [] | +| BondCalculator.owner | [] | +| BondCalculator.discountParams | [] | ++--------------------------------+--------------+ +INFO:Printers: +Contract IErrorsTokenomics ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +INFO:Printers: +Contract IErrorsTokenomics ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Contract IToken ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function balanceOf(address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| account | [] | +| | [] | ++----------+--------------+ +Function ownerOf(uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| tokenId | [] | +| | [] | ++----------+--------------+ +Function totalSupply() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function transfer(address,uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| to | [] | +| amount | [] | +| | [] | ++----------+--------------+ +Function allowance(address,address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| owner | [] | +| spender | [] | +| | [] | ++----------+--------------+ +Function approve(address,uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| spender | [] | +| amount | [] | +| | [] | ++----------+--------------+ +Function transferFrom(address,address,uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| from | [] | +| to | [] | +| amount | [] | +| | [] | ++----------+--------------+ +INFO:Printers: +Contract IErrorsTokenomics ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Contract IToken ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function balanceOf(address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| account | [] | +| | [] | ++----------+--------------+ +Function ownerOf(uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| tokenId | [] | +| | [] | ++----------+--------------+ +Function totalSupply() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function transfer(address,uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| to | [] | +| amount | [] | +| | [] | ++----------+--------------+ +Function allowance(address,address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| owner | [] | +| spender | [] | +| | [] | ++----------+--------------+ +Function approve(address,uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| spender | [] | +| amount | [] | +| | [] | ++----------+--------------+ +Function transferFrom(address,address,uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| from | [] | +| to | [] | +| amount | [] | +| | [] | ++----------+--------------+ +Contract ITokenomics ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function effectiveBond() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function checkpoint() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function trackServiceDonations(address,uint256[],uint256[],uint256) ++-------------+--------------+ +| Variable | Dependencies | ++-------------+--------------+ +| donator | [] | +| serviceIds | [] | +| amounts | [] | +| donationETH | [] | ++-------------+--------------+ +Function reserveAmountForBondProgram(uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| amount | [] | +| | [] | ++----------+--------------+ +Function refundFromBondProgram(uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| amount | [] | ++----------+--------------+ +Function accountOwnerIncentives(address,uint256[],uint256[]) ++-----------+--------------+ +| Variable | Dependencies | ++-----------+--------------+ +| account | [] | +| unitTypes | [] | +| unitIds | [] | +| reward | [] | +| topUp | [] | ++-----------+--------------+ +Function getLastIDF() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| idf | [] | ++----------+--------------+ +Function serviceRegistry() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +INFO:Printers: +Contract IErrorsTokenomics ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Contract IToken ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function balanceOf(address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| account | [] | +| | [] | ++----------+--------------+ +Function ownerOf(uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| tokenId | [] | +| | [] | ++----------+--------------+ +Function totalSupply() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function transfer(address,uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| to | [] | +| amount | [] | +| | [] | ++----------+--------------+ +Function allowance(address,address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| owner | [] | +| spender | [] | +| | [] | ++----------+--------------+ +Function approve(address,uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| spender | [] | +| amount | [] | +| | [] | ++----------+--------------+ +Function transferFrom(address,address,uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| from | [] | +| to | [] | +| amount | [] | +| | [] | ++----------+--------------+ +Contract ITokenomics ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function effectiveBond() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function checkpoint() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function trackServiceDonations(address,uint256[],uint256[],uint256) ++-------------+--------------+ +| Variable | Dependencies | ++-------------+--------------+ +| donator | [] | +| serviceIds | [] | +| amounts | [] | +| donationETH | [] | ++-------------+--------------+ +Function reserveAmountForBondProgram(uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| amount | [] | +| | [] | ++----------+--------------+ +Function refundFromBondProgram(uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| amount | [] | ++----------+--------------+ +Function accountOwnerIncentives(address,uint256[],uint256[]) ++-----------+--------------+ +| Variable | Dependencies | ++-----------+--------------+ +| account | [] | +| unitTypes | [] | +| unitIds | [] | +| reward | [] | +| topUp | [] | ++-----------+--------------+ +Function getLastIDF() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| idf | [] | ++----------+--------------+ +Function serviceRegistry() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Contract ITreasury ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function depositTokenForOLAS(address,uint256,address,uint256) ++---------------+--------------+ +| Variable | Dependencies | ++---------------+--------------+ +| account | [] | +| tokenAmount | [] | +| token | [] | +| olaMintAmount | [] | ++---------------+--------------+ +Function depositServiceDonationsETH(uint256[],uint256[]) ++------------+--------------+ +| Variable | Dependencies | ++------------+--------------+ +| serviceIds | [] | +| amounts | [] | ++------------+--------------+ +Function isEnabled(address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| token | [] | +| enabled | [] | ++----------+--------------+ +Function withdrawToAccount(address,uint256,uint256) ++----------------+--------------+ +| Variable | Dependencies | ++----------------+--------------+ +| account | [] | +| accountRewards | [] | +| accountTopUps | [] | +| success | [] | ++----------------+--------------+ +Function rebalanceTreasury(uint256) ++-----------------+--------------+ +| Variable | Dependencies | ++-----------------+--------------+ +| treasuryRewards | [] | +| success | [] | ++-----------------+--------------+ +INFO:Printers: +Contract IErrorsTokenomics ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Contract IToken ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function balanceOf(address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| account | [] | +| | [] | ++----------+--------------+ +Function ownerOf(uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| tokenId | [] | +| | [] | ++----------+--------------+ +Function totalSupply() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function transfer(address,uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| to | [] | +| amount | [] | +| | [] | ++----------+--------------+ +Function allowance(address,address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| owner | [] | +| spender | [] | +| | [] | ++----------+--------------+ +Function approve(address,uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| spender | [] | +| amount | [] | +| | [] | ++----------+--------------+ +Function transferFrom(address,address,uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| from | [] | +| to | [] | +| amount | [] | +| | [] | ++----------+--------------+ +Contract ITokenomics ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function effectiveBond() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function checkpoint() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function trackServiceDonations(address,uint256[],uint256[],uint256) ++-------------+--------------+ +| Variable | Dependencies | ++-------------+--------------+ +| donator | [] | +| serviceIds | [] | +| amounts | [] | +| donationETH | [] | ++-------------+--------------+ +Function reserveAmountForBondProgram(uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| amount | [] | +| | [] | ++----------+--------------+ +Function refundFromBondProgram(uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| amount | [] | ++----------+--------------+ +Function accountOwnerIncentives(address,uint256[],uint256[]) ++-----------+--------------+ +| Variable | Dependencies | ++-----------+--------------+ +| account | [] | +| unitTypes | [] | +| unitIds | [] | +| reward | [] | +| topUp | [] | ++-----------+--------------+ +Function getLastIDF() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| idf | [] | ++----------+--------------+ +Function serviceRegistry() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Contract ITreasury ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function depositTokenForOLAS(address,uint256,address,uint256) ++---------------+--------------+ +| Variable | Dependencies | ++---------------+--------------+ +| account | [] | +| tokenAmount | [] | +| token | [] | +| olaMintAmount | [] | ++---------------+--------------+ +Function depositServiceDonationsETH(uint256[],uint256[]) ++------------+--------------+ +| Variable | Dependencies | ++------------+--------------+ +| serviceIds | [] | +| amounts | [] | ++------------+--------------+ +Function isEnabled(address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| token | [] | +| enabled | [] | ++----------+--------------+ +Function withdrawToAccount(address,uint256,uint256) ++----------------+--------------+ +| Variable | Dependencies | ++----------------+--------------+ +| account | [] | +| accountRewards | [] | +| accountTopUps | [] | +| success | [] | ++----------------+--------------+ +Function rebalanceTreasury(uint256) ++-----------------+--------------+ +| Variable | Dependencies | ++-----------------+--------------+ +| treasuryRewards | [] | +| success | [] | ++-----------------+--------------+ +Contract ERC721 ++------------------+----------------------------+ +| Variable | Dependencies | ++------------------+----------------------------+ +| name | ['_name'] | +| symbol | ['_symbol'] | +| _ownerOf | ['_ownerOf', 'to'] | +| _balanceOf | ['_balanceOf'] | +| getApproved | ['getApproved', 'spender'] | +| isApprovedForAll | ['isApprovedForAll'] | ++------------------+----------------------------+ + +Function tokenURI(uint256) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| id | [] | +| | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function ownerOf(uint256) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| id | [] | +| owner | ['_ownerOf'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | ['_ownerOf'] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function balanceOf(address) ++-------------------------+----------------+ +| Variable | Dependencies | ++-------------------------+----------------+ +| owner | [] | +| | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | ['_balanceOf'] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+----------------+ +Function constructor(string,string) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| _name | ['_name'] | +| _symbol | ['_symbol'] | +| ERC721.name | ['_name'] | +| ERC721.symbol | ['_symbol'] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function approve(address,uint256) ++-------------------------+----------------------------+ +| Variable | Dependencies | ++-------------------------+----------------------------+ +| spender | [] | +| id | [] | +| owner | ['_ownerOf'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | ['_ownerOf'] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | ['getApproved', 'spender'] | +| ERC721.isApprovedForAll | ['isApprovedForAll'] | ++-------------------------+----------------------------+ +Function setApprovalForAll(address,bool) ++-------------------------+----------------------+ +| Variable | Dependencies | ++-------------------------+----------------------+ +| operator | [] | +| approved | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | ['isApprovedForAll'] | ++-------------------------+----------------------+ +Function transferFrom(address,address,uint256) ++-------------------------+----------------------+ +| Variable | Dependencies | ++-------------------------+----------------------+ +| from | ['from'] | +| to | ['to'] | +| id | ['id'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | ['_ownerOf', 'to'] | +| ERC721._balanceOf | ['_balanceOf'] | +| ERC721.getApproved | ['getApproved'] | +| ERC721.isApprovedForAll | ['isApprovedForAll'] | ++-------------------------+----------------------+ +Function safeTransferFrom(address,address,uint256) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| from | [] | +| to | [] | +| id | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function safeTransferFrom(address,address,uint256,bytes) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| from | [] | +| to | [] | +| id | [] | +| data | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function supportsInterface(bytes4) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| interfaceId | [] | +| | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function _mint(address,uint256) ++-------------------------+--------------------+ +| Variable | Dependencies | ++-------------------------+--------------------+ +| to | ['to'] | +| id | ['id'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | ['_ownerOf', 'to'] | +| ERC721._balanceOf | ['_balanceOf'] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------------+ +Function _burn(uint256) ++-------------------------+-----------------+ +| Variable | Dependencies | ++-------------------------+-----------------+ +| id | [] | +| owner | ['_ownerOf'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | ['_ownerOf'] | +| ERC721._balanceOf | ['_balanceOf'] | +| ERC721.getApproved | ['getApproved'] | +| ERC721.isApprovedForAll | [] | ++-------------------------+-----------------+ +Function _safeMint(address,uint256) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| to | [] | +| id | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function _safeMint(address,uint256,bytes) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| to | [] | +| id | [] | +| data | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +INFO:Printers: +Contract IErrorsTokenomics ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Contract IToken ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function balanceOf(address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| account | [] | +| | [] | ++----------+--------------+ +Function ownerOf(uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| tokenId | [] | +| | [] | ++----------+--------------+ +Function totalSupply() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function transfer(address,uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| to | [] | +| amount | [] | +| | [] | ++----------+--------------+ +Function allowance(address,address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| owner | [] | +| spender | [] | +| | [] | ++----------+--------------+ +Function approve(address,uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| spender | [] | +| amount | [] | +| | [] | ++----------+--------------+ +Function transferFrom(address,address,uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| from | [] | +| to | [] | +| amount | [] | +| | [] | ++----------+--------------+ +Contract ITokenomics ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function effectiveBond() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function checkpoint() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function trackServiceDonations(address,uint256[],uint256[],uint256) ++-------------+--------------+ +| Variable | Dependencies | ++-------------+--------------+ +| donator | [] | +| serviceIds | [] | +| amounts | [] | +| donationETH | [] | ++-------------+--------------+ +Function reserveAmountForBondProgram(uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| amount | [] | +| | [] | ++----------+--------------+ +Function refundFromBondProgram(uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| amount | [] | ++----------+--------------+ +Function accountOwnerIncentives(address,uint256[],uint256[]) ++-----------+--------------+ +| Variable | Dependencies | ++-----------+--------------+ +| account | [] | +| unitTypes | [] | +| unitIds | [] | +| reward | [] | +| topUp | [] | ++-----------+--------------+ +Function getLastIDF() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| idf | [] | ++----------+--------------+ +Function serviceRegistry() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Contract ITreasury ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function depositTokenForOLAS(address,uint256,address,uint256) ++---------------+--------------+ +| Variable | Dependencies | ++---------------+--------------+ +| account | [] | +| tokenAmount | [] | +| token | [] | +| olaMintAmount | [] | ++---------------+--------------+ +Function depositServiceDonationsETH(uint256[],uint256[]) ++------------+--------------+ +| Variable | Dependencies | ++------------+--------------+ +| serviceIds | [] | +| amounts | [] | ++------------+--------------+ +Function isEnabled(address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| token | [] | +| enabled | [] | ++----------+--------------+ +Function withdrawToAccount(address,uint256,uint256) ++----------------+--------------+ +| Variable | Dependencies | ++----------------+--------------+ +| account | [] | +| accountRewards | [] | +| accountTopUps | [] | +| success | [] | ++----------------+--------------+ +Function rebalanceTreasury(uint256) ++-----------------+--------------+ +| Variable | Dependencies | ++-----------------+--------------+ +| treasuryRewards | [] | +| success | [] | ++-----------------+--------------+ +Contract ERC721 ++------------------+----------------------------+ +| Variable | Dependencies | ++------------------+----------------------------+ +| name | ['_name'] | +| symbol | ['_symbol'] | +| _ownerOf | ['_ownerOf', 'to'] | +| _balanceOf | ['_balanceOf'] | +| getApproved | ['getApproved', 'spender'] | +| isApprovedForAll | ['isApprovedForAll'] | ++------------------+----------------------------+ + +Function tokenURI(uint256) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| id | [] | +| | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function ownerOf(uint256) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| id | [] | +| owner | ['_ownerOf'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | ['_ownerOf'] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function balanceOf(address) ++-------------------------+----------------+ +| Variable | Dependencies | ++-------------------------+----------------+ +| owner | [] | +| | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | ['_balanceOf'] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+----------------+ +Function constructor(string,string) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| _name | ['_name'] | +| _symbol | ['_symbol'] | +| ERC721.name | ['_name'] | +| ERC721.symbol | ['_symbol'] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function approve(address,uint256) ++-------------------------+----------------------------+ +| Variable | Dependencies | ++-------------------------+----------------------------+ +| spender | [] | +| id | [] | +| owner | ['_ownerOf'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | ['_ownerOf'] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | ['getApproved', 'spender'] | +| ERC721.isApprovedForAll | ['isApprovedForAll'] | ++-------------------------+----------------------------+ +Function setApprovalForAll(address,bool) ++-------------------------+----------------------+ +| Variable | Dependencies | ++-------------------------+----------------------+ +| operator | [] | +| approved | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | ['isApprovedForAll'] | ++-------------------------+----------------------+ +Function transferFrom(address,address,uint256) ++-------------------------+----------------------+ +| Variable | Dependencies | ++-------------------------+----------------------+ +| from | ['from'] | +| to | ['to'] | +| id | ['id'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | ['_ownerOf', 'to'] | +| ERC721._balanceOf | ['_balanceOf'] | +| ERC721.getApproved | ['getApproved'] | +| ERC721.isApprovedForAll | ['isApprovedForAll'] | ++-------------------------+----------------------+ +Function safeTransferFrom(address,address,uint256) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| from | [] | +| to | [] | +| id | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function safeTransferFrom(address,address,uint256,bytes) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| from | [] | +| to | [] | +| id | [] | +| data | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function supportsInterface(bytes4) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| interfaceId | [] | +| | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function _mint(address,uint256) ++-------------------------+--------------------+ +| Variable | Dependencies | ++-------------------------+--------------------+ +| to | ['to'] | +| id | ['id'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | ['_ownerOf', 'to'] | +| ERC721._balanceOf | ['_balanceOf'] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------------+ +Function _burn(uint256) ++-------------------------+-----------------+ +| Variable | Dependencies | ++-------------------------+-----------------+ +| id | [] | +| owner | ['_ownerOf'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | ['_ownerOf'] | +| ERC721._balanceOf | ['_balanceOf'] | +| ERC721.getApproved | ['getApproved'] | +| ERC721.isApprovedForAll | [] | ++-------------------------+-----------------+ +Function _safeMint(address,uint256) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| to | [] | +| id | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function _safeMint(address,uint256,bytes) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| to | [] | +| id | [] | +| data | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Contract ERC721TokenReceiver ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function onERC721Received(address,address,uint256,bytes) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +INFO:Printers: +Contract IErrorsTokenomics ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Contract IToken ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function balanceOf(address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| account | [] | +| | [] | ++----------+--------------+ +Function ownerOf(uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| tokenId | [] | +| | [] | ++----------+--------------+ +Function totalSupply() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function transfer(address,uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| to | [] | +| amount | [] | +| | [] | ++----------+--------------+ +Function allowance(address,address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| owner | [] | +| spender | [] | +| | [] | ++----------+--------------+ +Function approve(address,uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| spender | [] | +| amount | [] | +| | [] | ++----------+--------------+ +Function transferFrom(address,address,uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| from | [] | +| to | [] | +| amount | [] | +| | [] | ++----------+--------------+ +Contract ITokenomics ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function effectiveBond() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function checkpoint() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function trackServiceDonations(address,uint256[],uint256[],uint256) ++-------------+--------------+ +| Variable | Dependencies | ++-------------+--------------+ +| donator | [] | +| serviceIds | [] | +| amounts | [] | +| donationETH | [] | ++-------------+--------------+ +Function reserveAmountForBondProgram(uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| amount | [] | +| | [] | ++----------+--------------+ +Function refundFromBondProgram(uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| amount | [] | ++----------+--------------+ +Function accountOwnerIncentives(address,uint256[],uint256[]) ++-----------+--------------+ +| Variable | Dependencies | ++-----------+--------------+ +| account | [] | +| unitTypes | [] | +| unitIds | [] | +| reward | [] | +| topUp | [] | ++-----------+--------------+ +Function getLastIDF() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| idf | [] | ++----------+--------------+ +Function serviceRegistry() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Contract ITreasury ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function depositTokenForOLAS(address,uint256,address,uint256) ++---------------+--------------+ +| Variable | Dependencies | ++---------------+--------------+ +| account | [] | +| tokenAmount | [] | +| token | [] | +| olaMintAmount | [] | ++---------------+--------------+ +Function depositServiceDonationsETH(uint256[],uint256[]) ++------------+--------------+ +| Variable | Dependencies | ++------------+--------------+ +| serviceIds | [] | +| amounts | [] | ++------------+--------------+ +Function isEnabled(address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| token | [] | +| enabled | [] | ++----------+--------------+ +Function withdrawToAccount(address,uint256,uint256) ++----------------+--------------+ +| Variable | Dependencies | ++----------------+--------------+ +| account | [] | +| accountRewards | [] | +| accountTopUps | [] | +| success | [] | ++----------------+--------------+ +Function rebalanceTreasury(uint256) ++-----------------+--------------+ +| Variable | Dependencies | ++-----------------+--------------+ +| treasuryRewards | [] | +| success | [] | ++-----------------+--------------+ +Contract ERC721 ++------------------+----------------------------+ +| Variable | Dependencies | ++------------------+----------------------------+ +| name | ['_name'] | +| symbol | ['_symbol'] | +| _ownerOf | ['_ownerOf', 'to'] | +| _balanceOf | ['_balanceOf'] | +| getApproved | ['getApproved', 'spender'] | +| isApprovedForAll | ['isApprovedForAll'] | ++------------------+----------------------------+ + +Function tokenURI(uint256) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| id | [] | +| | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function ownerOf(uint256) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| id | [] | +| owner | ['_ownerOf'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | ['_ownerOf'] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function balanceOf(address) ++-------------------------+----------------+ +| Variable | Dependencies | ++-------------------------+----------------+ +| owner | [] | +| | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | ['_balanceOf'] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+----------------+ +Function constructor(string,string) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| _name | ['_name'] | +| _symbol | ['_symbol'] | +| ERC721.name | ['_name'] | +| ERC721.symbol | ['_symbol'] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function approve(address,uint256) ++-------------------------+----------------------------+ +| Variable | Dependencies | ++-------------------------+----------------------------+ +| spender | [] | +| id | [] | +| owner | ['_ownerOf'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | ['_ownerOf'] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | ['getApproved', 'spender'] | +| ERC721.isApprovedForAll | ['isApprovedForAll'] | ++-------------------------+----------------------------+ +Function setApprovalForAll(address,bool) ++-------------------------+----------------------+ +| Variable | Dependencies | ++-------------------------+----------------------+ +| operator | [] | +| approved | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | ['isApprovedForAll'] | ++-------------------------+----------------------+ +Function transferFrom(address,address,uint256) ++-------------------------+----------------------+ +| Variable | Dependencies | ++-------------------------+----------------------+ +| from | ['from'] | +| to | ['to'] | +| id | ['id'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | ['_ownerOf', 'to'] | +| ERC721._balanceOf | ['_balanceOf'] | +| ERC721.getApproved | ['getApproved'] | +| ERC721.isApprovedForAll | ['isApprovedForAll'] | ++-------------------------+----------------------+ +Function safeTransferFrom(address,address,uint256) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| from | [] | +| to | [] | +| id | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function safeTransferFrom(address,address,uint256,bytes) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| from | [] | +| to | [] | +| id | [] | +| data | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function supportsInterface(bytes4) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| interfaceId | [] | +| | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function _mint(address,uint256) ++-------------------------+--------------------+ +| Variable | Dependencies | ++-------------------------+--------------------+ +| to | ['to'] | +| id | ['id'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | ['_ownerOf', 'to'] | +| ERC721._balanceOf | ['_balanceOf'] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------------+ +Function _burn(uint256) ++-------------------------+-----------------+ +| Variable | Dependencies | ++-------------------------+-----------------+ +| id | [] | +| owner | ['_ownerOf'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | ['_ownerOf'] | +| ERC721._balanceOf | ['_balanceOf'] | +| ERC721.getApproved | ['getApproved'] | +| ERC721.isApprovedForAll | [] | ++-------------------------+-----------------+ +Function _safeMint(address,uint256) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| to | [] | +| id | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function _safeMint(address,uint256,bytes) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| to | [] | +| id | [] | +| data | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Contract ERC721TokenReceiver ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function onERC721Received(address,address,uint256,bytes) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Contract IBondCalculator ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function calculatePayoutOLAS(address,uint256,uint256,uint256,uint256,uint256,uint256) ++-----------------------+--------------+ +| Variable | Dependencies | ++-----------------------+--------------+ +| account | [] | +| tokenAmount | [] | +| priceLP | [] | +| bondVestingTime | [] | +| productMaxVestingTime | [] | +| productSupply | [] | +| productPayout | [] | +| amountOLAS | [] | ++-----------------------+--------------+ +Function getCurrentPriceLP(address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| token | [] | +| priceLP | [] | ++----------+--------------+ +INFO:Printers: +Contract IErrorsTokenomics ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Contract IToken ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function balanceOf(address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| account | [] | +| | [] | ++----------+--------------+ +Function ownerOf(uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| tokenId | [] | +| | [] | ++----------+--------------+ +Function totalSupply() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function transfer(address,uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| to | [] | +| amount | [] | +| | [] | ++----------+--------------+ +Function allowance(address,address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| owner | [] | +| spender | [] | +| | [] | ++----------+--------------+ +Function approve(address,uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| spender | [] | +| amount | [] | +| | [] | ++----------+--------------+ +Function transferFrom(address,address,uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| from | [] | +| to | [] | +| amount | [] | +| | [] | ++----------+--------------+ +Contract ITokenomics ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function effectiveBond() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function checkpoint() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Function trackServiceDonations(address,uint256[],uint256[],uint256) ++-------------+--------------+ +| Variable | Dependencies | ++-------------+--------------+ +| donator | [] | +| serviceIds | [] | +| amounts | [] | +| donationETH | [] | ++-------------+--------------+ +Function reserveAmountForBondProgram(uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| amount | [] | +| | [] | ++----------+--------------+ +Function refundFromBondProgram(uint256) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| amount | [] | ++----------+--------------+ +Function accountOwnerIncentives(address,uint256[],uint256[]) ++-----------+--------------+ +| Variable | Dependencies | ++-----------+--------------+ +| account | [] | +| unitTypes | [] | +| unitIds | [] | +| reward | [] | +| topUp | [] | ++-----------+--------------+ +Function getLastIDF() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| idf | [] | ++----------+--------------+ +Function serviceRegistry() ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Contract ITreasury ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function depositTokenForOLAS(address,uint256,address,uint256) ++---------------+--------------+ +| Variable | Dependencies | ++---------------+--------------+ +| account | [] | +| tokenAmount | [] | +| token | [] | +| olaMintAmount | [] | ++---------------+--------------+ +Function depositServiceDonationsETH(uint256[],uint256[]) ++------------+--------------+ +| Variable | Dependencies | ++------------+--------------+ +| serviceIds | [] | +| amounts | [] | ++------------+--------------+ +Function isEnabled(address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| token | [] | +| enabled | [] | ++----------+--------------+ +Function withdrawToAccount(address,uint256,uint256) ++----------------+--------------+ +| Variable | Dependencies | ++----------------+--------------+ +| account | [] | +| accountRewards | [] | +| accountTopUps | [] | +| success | [] | ++----------------+--------------+ +Function rebalanceTreasury(uint256) ++-----------------+--------------+ +| Variable | Dependencies | ++-----------------+--------------+ +| treasuryRewards | [] | +| success | [] | ++-----------------+--------------+ +Contract ERC721 ++------------------+----------------------------+ +| Variable | Dependencies | ++------------------+----------------------------+ +| name | ['_name'] | +| symbol | ['_symbol'] | +| _ownerOf | ['_ownerOf', 'to'] | +| _balanceOf | ['_balanceOf'] | +| getApproved | ['getApproved', 'spender'] | +| isApprovedForAll | ['isApprovedForAll'] | ++------------------+----------------------------+ + +Function tokenURI(uint256) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| id | [] | +| | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function ownerOf(uint256) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| id | [] | +| owner | ['_ownerOf'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | ['_ownerOf'] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function balanceOf(address) ++-------------------------+----------------+ +| Variable | Dependencies | ++-------------------------+----------------+ +| owner | [] | +| | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | ['_balanceOf'] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+----------------+ +Function constructor(string,string) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| _name | ['_name'] | +| _symbol | ['_symbol'] | +| ERC721.name | ['_name'] | +| ERC721.symbol | ['_symbol'] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function approve(address,uint256) ++-------------------------+----------------------------+ +| Variable | Dependencies | ++-------------------------+----------------------------+ +| spender | [] | +| id | [] | +| owner | ['_ownerOf'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | ['_ownerOf'] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | ['getApproved', 'spender'] | +| ERC721.isApprovedForAll | ['isApprovedForAll'] | ++-------------------------+----------------------------+ +Function setApprovalForAll(address,bool) ++-------------------------+----------------------+ +| Variable | Dependencies | ++-------------------------+----------------------+ +| operator | [] | +| approved | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | ['isApprovedForAll'] | ++-------------------------+----------------------+ +Function transferFrom(address,address,uint256) ++-------------------------+----------------------+ +| Variable | Dependencies | ++-------------------------+----------------------+ +| from | ['from'] | +| to | ['to'] | +| id | ['id'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | ['_ownerOf', 'to'] | +| ERC721._balanceOf | ['_balanceOf'] | +| ERC721.getApproved | ['getApproved'] | +| ERC721.isApprovedForAll | ['isApprovedForAll'] | ++-------------------------+----------------------+ +Function safeTransferFrom(address,address,uint256) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| from | [] | +| to | [] | +| id | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function safeTransferFrom(address,address,uint256,bytes) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| from | [] | +| to | [] | +| id | [] | +| data | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function supportsInterface(bytes4) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| interfaceId | [] | +| | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function _mint(address,uint256) ++-------------------------+--------------------+ +| Variable | Dependencies | ++-------------------------+--------------------+ +| to | ['to'] | +| id | ['id'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | ['_ownerOf', 'to'] | +| ERC721._balanceOf | ['_balanceOf'] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------------+ +Function _burn(uint256) ++-------------------------+-----------------+ +| Variable | Dependencies | ++-------------------------+-----------------+ +| id | [] | +| owner | ['_ownerOf'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | ['_ownerOf'] | +| ERC721._balanceOf | ['_balanceOf'] | +| ERC721.getApproved | ['getApproved'] | +| ERC721.isApprovedForAll | [] | ++-------------------------+-----------------+ +Function _safeMint(address,uint256) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| to | [] | +| id | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Function _safeMint(address,uint256,bytes) ++-------------------------+--------------+ +| Variable | Dependencies | ++-------------------------+--------------+ +| to | [] | +| id | [] | +| data | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | ++-------------------------+--------------+ +Contract ERC721TokenReceiver ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function onERC721Received(address,address,uint256,bytes) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| | [] | ++----------+--------------+ +Contract IBondCalculator ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ ++----------+--------------+ + +Function calculatePayoutOLAS(address,uint256,uint256,uint256,uint256,uint256,uint256) ++-----------------------+--------------+ +| Variable | Dependencies | ++-----------------------+--------------+ +| account | [] | +| tokenAmount | [] | +| priceLP | [] | +| bondVestingTime | [] | +| productMaxVestingTime | [] | +| productSupply | [] | +| productPayout | [] | +| amountOLAS | [] | ++-----------------------+--------------+ +Function getCurrentPriceLP(address) ++----------+--------------+ +| Variable | Dependencies | ++----------+--------------+ +| token | [] | +| priceLP | [] | ++----------+--------------+ +Contract Depository ++-----------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Variable | Dependencies | ++-----------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| name | ['_name'] | +| symbol | ['_symbol'] | +| _ownerOf | ['_ownerOf', 'msg.sender', 'to'] | +| _balanceOf | ['_balanceOf'] | +| getApproved | ['getApproved', 'spender'] | +| isApprovedForAll | ['isApprovedForAll'] | +| MIN_VESTING | ['MIN_VESTING'] | +| VERSION | [] | +| baseURI | ['_baseURI', 'baseURI'] | +| owner | ['msg.sender', 'newOwner', 'owner'] | +| totalSupply | ['bondId', 'totalSupply'] | +| productCounter | ['productCounter', 'productId'] | +| minOLASLeftoverAmount | ['minOLASLeftoverAmount'] | +| olas | ['_olas', 'olas'] | +| tokenomics | ['_tokenomics', 'tokenomics'] | +| treasury | ['_treasury', 'treasury'] | +| bondCalculator | ['_bondCalculator', 'bondCalculator'] | +| mapUserBonds | ['_bondCalculator', 'block.timestamp', 'bondCalculator', 'bondVestingTime', 'mapUserBonds', 'maturity', 'msg.sender', 'payout', 'product', 'productId', 'productMaxVestingTime', 'supply', 'tokenAmount'] | +| mapBondProducts | ['_bondCalculator', 'bondCalculator', 'bondVestingTime', 'mapBondProducts', 'msg.sender', 'payout', 'priceLP', 'product', 'productMaxVestingTime', 'supply', 'token', 'tokenAmount', 'vesting'] | ++-----------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +Function constructor(string,string,string,address,address,address,address) ++----------------------------------+---------------------+ +| Variable | Dependencies | ++----------------------------------+---------------------+ +| _name | [] | +| _symbol | [] | +| _baseURI | [] | +| _olas | [] | +| _tokenomics | [] | +| _treasury | [] | +| _bondCalculator | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | +| Depository.MIN_VESTING | [] | +| Depository.VERSION | [] | +| Depository.baseURI | ['_baseURI'] | +| Depository.owner | ['msg.sender'] | +| Depository.totalSupply | [] | +| Depository.productCounter | [] | +| Depository.minOLASLeftoverAmount | [] | +| Depository.olas | ['_olas'] | +| Depository.tokenomics | ['_tokenomics'] | +| Depository.treasury | ['_treasury'] | +| Depository.bondCalculator | ['_bondCalculator'] | +| Depository.mapUserBonds | [] | +| Depository.mapBondProducts | [] | ++----------------------------------+---------------------+ +Function changeOwner(address) ++----------------------------------+-----------------------+ +| Variable | Dependencies | ++----------------------------------+-----------------------+ +| newOwner | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | +| Depository.MIN_VESTING | [] | +| Depository.VERSION | [] | +| Depository.baseURI | [] | +| Depository.owner | ['newOwner', 'owner'] | +| Depository.totalSupply | [] | +| Depository.productCounter | [] | +| Depository.minOLASLeftoverAmount | [] | +| Depository.olas | [] | +| Depository.tokenomics | [] | +| Depository.treasury | [] | +| Depository.bondCalculator | [] | +| Depository.mapUserBonds | [] | +| Depository.mapBondProducts | [] | ++----------------------------------+-----------------------+ +Function changeManagers(address,address) ++----------------------------------+-----------------+ +| Variable | Dependencies | ++----------------------------------+-----------------+ +| _tokenomics | [] | +| _treasury | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | +| Depository.MIN_VESTING | [] | +| Depository.VERSION | [] | +| Depository.baseURI | [] | +| Depository.owner | ['owner'] | +| Depository.totalSupply | [] | +| Depository.productCounter | [] | +| Depository.minOLASLeftoverAmount | [] | +| Depository.olas | [] | +| Depository.tokenomics | ['_tokenomics'] | +| Depository.treasury | ['_treasury'] | +| Depository.bondCalculator | [] | +| Depository.mapUserBonds | [] | +| Depository.mapBondProducts | [] | ++----------------------------------+-----------------+ +Function changeBondCalculator(address) ++----------------------------------+---------------------+ +| Variable | Dependencies | ++----------------------------------+---------------------+ +| _bondCalculator | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | +| Depository.MIN_VESTING | [] | +| Depository.VERSION | [] | +| Depository.baseURI | [] | +| Depository.owner | ['owner'] | +| Depository.totalSupply | [] | +| Depository.productCounter | [] | +| Depository.minOLASLeftoverAmount | [] | +| Depository.olas | [] | +| Depository.tokenomics | [] | +| Depository.treasury | [] | +| Depository.bondCalculator | ['_bondCalculator'] | +| Depository.mapUserBonds | [] | +| Depository.mapBondProducts | [] | ++----------------------------------+---------------------+ +Function create(address,uint256,uint256,uint256) ++----------------------------------+--------------------------------------------------------------+ +| Variable | Dependencies | ++----------------------------------+--------------------------------------------------------------+ +| token | [] | +| priceLP | [] | +| supply | [] | +| vesting | [] | +| productId | ['productCounter'] | +| maturity | ['block.timestamp', 'vesting'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | +| Depository.MIN_VESTING | ['MIN_VESTING'] | +| Depository.VERSION | [] | +| Depository.baseURI | [] | +| Depository.owner | ['owner'] | +| Depository.totalSupply | [] | +| Depository.productCounter | ['productCounter', 'productId'] | +| Depository.minOLASLeftoverAmount | [] | +| Depository.olas | [] | +| Depository.tokenomics | ['tokenomics'] | +| Depository.treasury | ['treasury'] | +| Depository.bondCalculator | [] | +| Depository.mapUserBonds | [] | +| Depository.mapBondProducts | ['mapBondProducts', 'priceLP', 'supply', 'token', 'vesting'] | ++----------------------------------+--------------------------------------------------------------+ +Function close(uint256[]) ++----------------------------------+-------------------------------------------------------------------------------+ +| Variable | Dependencies | ++----------------------------------+-------------------------------------------------------------------------------+ +| productIds | ['productIds'] | +| closedProductIds | ['closedProductIds', 'ids', 'numClosedProducts', 'numProducts', 'productIds'] | +| numProducts | ['productIds'] | +| ids | ['ids', 'numProducts', 'productIds'] | +| numClosedProducts | ['numClosedProducts'] | +| i | ['i'] | +| productId | ['productIds'] | +| supply | ['mapBondProducts'] | +| token | ['mapBondProducts'] | +| i_scope_0 | ['i_scope_0'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | +| Depository.MIN_VESTING | [] | +| Depository.VERSION | [] | +| Depository.baseURI | [] | +| Depository.owner | ['owner'] | +| Depository.totalSupply | [] | +| Depository.productCounter | [] | +| Depository.minOLASLeftoverAmount | [] | +| Depository.olas | [] | +| Depository.tokenomics | ['tokenomics'] | +| Depository.treasury | [] | +| Depository.bondCalculator | [] | +| Depository.mapUserBonds | [] | +| Depository.mapBondProducts | ['mapBondProducts'] | ++----------------------------------+-------------------------------------------------------------------------------+ +Function deposit(uint256,uint256,uint256) ++----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Variable | Dependencies | ++----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| productId | [] | +| tokenAmount | [] | +| bondVestingTime | [] | +| payout | ['bondCalculator', 'bondVestingTime', 'msg.sender', 'payout', 'product', 'productMaxVestingTime', 'supply', 'tokenAmount'] | +| maturity | ['block.timestamp', 'bondVestingTime'] | +| bondId | ['totalSupply'] | +| product | ['bondCalculator', 'bondVestingTime', 'msg.sender', 'payout', 'product', 'productMaxVestingTime', 'supply', 'tokenAmount'] | +| supply | ['bondCalculator', 'bondVestingTime', 'msg.sender', 'payout', 'product', 'productMaxVestingTime', 'supply', 'tokenAmount'] | +| productMaxVestingTime | ['product'] | +| token | ['product'] | +| olasBalance | ['olas', 'olasBalance', 'this'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | +| Depository.MIN_VESTING | ['MIN_VESTING'] | +| Depository.VERSION | [] | +| Depository.baseURI | [] | +| Depository.owner | [] | +| Depository.totalSupply | ['bondId', 'totalSupply'] | +| Depository.productCounter | [] | +| Depository.minOLASLeftoverAmount | ['minOLASLeftoverAmount'] | +| Depository.olas | ['olas'] | +| Depository.tokenomics | [] | +| Depository.treasury | ['treasury'] | +| Depository.bondCalculator | ['bondCalculator'] | +| Depository.mapUserBonds | ['block.timestamp', 'bondCalculator', 'bondVestingTime', 'mapUserBonds', 'maturity', 'msg.sender', 'payout', 'product', 'productId', 'productMaxVestingTime', 'supply', 'tokenAmount'] | +| Depository.mapBondProducts | ['bondCalculator', 'bondVestingTime', 'mapBondProducts', 'msg.sender', 'payout', 'product', 'productMaxVestingTime', 'supply', 'tokenAmount'] | ++----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +Function redeem(uint256[]) ++----------------------------------+-------------------------------------+ +| Variable | Dependencies | ++----------------------------------+-------------------------------------+ +| bondIds | ['bondIds'] | +| payout | ['mapUserBonds', 'pay', 'payout'] | +| i | ['i'] | +| pay | ['mapUserBonds'] | +| matured | ['block.timestamp', 'mapUserBonds'] | +| bondOwner | ['_ownerOf'] | +| productId | ['mapUserBonds'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | ['_ownerOf'] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | +| Depository.MIN_VESTING | [] | +| Depository.VERSION | [] | +| Depository.baseURI | [] | +| Depository.owner | [] | +| Depository.totalSupply | [] | +| Depository.productCounter | [] | +| Depository.minOLASLeftoverAmount | [] | +| Depository.olas | ['olas'] | +| Depository.tokenomics | [] | +| Depository.treasury | [] | +| Depository.bondCalculator | [] | +| Depository.mapUserBonds | ['mapUserBonds'] | +| Depository.mapBondProducts | [] | ++----------------------------------+-------------------------------------+ +Function getProducts(bool) ++----------------------------------+----------------------------------------------------+ +| Variable | Dependencies | ++----------------------------------+----------------------------------------------------+ +| active | [] | +| productIds | ['i_scope_0', 'numSelectedProducts', 'productIds'] | +| numProducts | ['productCounter'] | +| positions | ['numProducts', 'positions', 'productCounter'] | +| numSelectedProducts | ['numSelectedProducts'] | +| i | ['i'] | +| numPos | ['numPos'] | +| i_scope_0 | ['i_scope_0'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | +| Depository.MIN_VESTING | [] | +| Depository.VERSION | [] | +| Depository.baseURI | [] | +| Depository.owner | [] | +| Depository.totalSupply | [] | +| Depository.productCounter | ['productCounter'] | +| Depository.minOLASLeftoverAmount | [] | +| Depository.olas | [] | +| Depository.tokenomics | [] | +| Depository.treasury | [] | +| Depository.bondCalculator | [] | +| Depository.mapUserBonds | [] | +| Depository.mapBondProducts | ['mapBondProducts'] | ++----------------------------------+----------------------------------------------------+ +Function isActiveProduct(uint256) ++----------------------------------+---------------------+ +| Variable | Dependencies | ++----------------------------------+---------------------+ +| productId | [] | +| status | ['mapBondProducts'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | +| Depository.MIN_VESTING | [] | +| Depository.VERSION | [] | +| Depository.baseURI | [] | +| Depository.owner | [] | +| Depository.totalSupply | [] | +| Depository.productCounter | [] | +| Depository.minOLASLeftoverAmount | [] | +| Depository.olas | [] | +| Depository.tokenomics | [] | +| Depository.treasury | [] | +| Depository.bondCalculator | [] | +| Depository.mapUserBonds | [] | +| Depository.mapBondProducts | ['mapBondProducts'] | ++----------------------------------+---------------------+ +Function getBonds(address,bool) ++----------------------------------+---------------------------------------------+ +| Variable | Dependencies | ++----------------------------------+---------------------------------------------+ +| account | [] | +| matured | [] | +| bondIds | ['bondIds', 'i_scope_0', 'numAccountBonds'] | +| payout | ['mapUserBonds', 'payout'] | +| numAccountBonds | ['numAccountBonds'] | +| numBonds | ['totalSupply'] | +| positions | ['numBonds', 'positions', 'totalSupply'] | +| i | ['i'] | +| numPos | ['numPos'] | +| i_scope_0 | ['i_scope_0'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | ['_ownerOf'] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | +| Depository.MIN_VESTING | [] | +| Depository.VERSION | [] | +| Depository.baseURI | [] | +| Depository.owner | [] | +| Depository.totalSupply | ['totalSupply'] | +| Depository.productCounter | [] | +| Depository.minOLASLeftoverAmount | [] | +| Depository.olas | [] | +| Depository.tokenomics | [] | +| Depository.treasury | [] | +| Depository.bondCalculator | [] | +| Depository.mapUserBonds | ['mapUserBonds'] | +| Depository.mapBondProducts | [] | ++----------------------------------+---------------------------------------------+ +Function getBondStatus(uint256) ++----------------------------------+-------------------------------------+ +| Variable | Dependencies | ++----------------------------------+-------------------------------------+ +| bondId | [] | +| payout | ['mapUserBonds'] | +| matured | ['block.timestamp', 'mapUserBonds'] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | +| Depository.MIN_VESTING | [] | +| Depository.VERSION | [] | +| Depository.baseURI | [] | +| Depository.owner | [] | +| Depository.totalSupply | [] | +| Depository.productCounter | [] | +| Depository.minOLASLeftoverAmount | [] | +| Depository.olas | [] | +| Depository.tokenomics | [] | +| Depository.treasury | [] | +| Depository.bondCalculator | [] | +| Depository.mapUserBonds | ['mapUserBonds'] | +| Depository.mapBondProducts | [] | ++----------------------------------+-------------------------------------+ +Function getCurrentPriceLP(address) ++----------------------------------+--------------------+ +| Variable | Dependencies | ++----------------------------------+--------------------+ +| token | [] | +| priceLP | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | +| Depository.MIN_VESTING | [] | +| Depository.VERSION | [] | +| Depository.baseURI | [] | +| Depository.owner | [] | +| Depository.totalSupply | [] | +| Depository.productCounter | [] | +| Depository.minOLASLeftoverAmount | [] | +| Depository.olas | [] | +| Depository.tokenomics | [] | +| Depository.treasury | [] | +| Depository.bondCalculator | ['bondCalculator'] | +| Depository.mapUserBonds | [] | +| Depository.mapBondProducts | [] | ++----------------------------------+--------------------+ +Function tokenByIndex(uint256) ++----------------------------------+-----------------+ +| Variable | Dependencies | ++----------------------------------+-----------------+ +| id | [] | +| | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | +| Depository.MIN_VESTING | [] | +| Depository.VERSION | [] | +| Depository.baseURI | [] | +| Depository.owner | [] | +| Depository.totalSupply | ['totalSupply'] | +| Depository.productCounter | [] | +| Depository.minOLASLeftoverAmount | [] | +| Depository.olas | [] | +| Depository.tokenomics | [] | +| Depository.treasury | [] | +| Depository.bondCalculator | [] | +| Depository.mapUserBonds | [] | +| Depository.mapBondProducts | [] | ++----------------------------------+-----------------+ +Function tokenURI(uint256) ++----------------------------------+--------------+ +| Variable | Dependencies | ++----------------------------------+--------------+ +| bondId | [] | +| | [] | +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | +| Depository.MIN_VESTING | [] | +| Depository.VERSION | [] | +| Depository.baseURI | ['baseURI'] | +| Depository.owner | [] | +| Depository.totalSupply | [] | +| Depository.productCounter | [] | +| Depository.minOLASLeftoverAmount | [] | +| Depository.olas | [] | +| Depository.tokenomics | [] | +| Depository.treasury | [] | +| Depository.bondCalculator | [] | +| Depository.mapUserBonds | [] | +| Depository.mapBondProducts | [] | ++----------------------------------+--------------+ +Function slitherConstructorConstantVariables() ++----------------------------------+--------------+ +| Variable | Dependencies | ++----------------------------------+--------------+ +| ERC721.name | [] | +| ERC721.symbol | [] | +| ERC721._ownerOf | [] | +| ERC721._balanceOf | [] | +| ERC721.getApproved | [] | +| ERC721.isApprovedForAll | [] | +| Depository.MIN_VESTING | [] | +| Depository.VERSION | [] | +| Depository.baseURI | [] | +| Depository.owner | [] | +| Depository.totalSupply | [] | +| Depository.productCounter | [] | +| Depository.minOLASLeftoverAmount | [] | +| Depository.olas | [] | +| Depository.tokenomics | [] | +| Depository.treasury | [] | +| Depository.bondCalculator | [] | +| Depository.mapUserBonds | [] | +| Depository.mapBondProducts | [] | ++----------------------------------+--------------+ +INFO:Slither:. analyzed (12 contracts) diff --git a/audits/internal6/analysis/slither_full.txt b/audits/internal6/analysis/slither_full.txt new file mode 100644 index 00000000..ffd1ffa0 --- /dev/null +++ b/audits/internal6/analysis/slither_full.txt @@ -0,0 +1,452 @@ +Notes: False positive +INFO:Detectors: +BondCalculator.calculateIDF(address,uint256,uint256,uint256,uint256).discountBooster (BondCalculator-flatten.sol#868) is a local variable never initialized +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-local-variables + +Notes: by design +INFO:Detectors: +BondCalculator.getCurrentPriceLP(address) (BondCalculator-flatten.sol#971-992) ignores return value by (reserve0,reserve1,None) = pair.getReserves() (BondCalculator-flatten.sol#980) +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#unused-return + +Notes: out of scope +INFO:Detectors: +exp2(uint256) (BondCalculator-flatten.sol#55-293) has a high cyclomatic complexity (73). +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#cyclomatic-complexity + +Notes: out of scope, external lib +INFO:Detectors: +exp2(uint256) (BondCalculator-flatten.sol#55-293) is never used and should be removed +msb(uint256) (BondCalculator-flatten.sol#321-370) is never used and should be removed +mulDiv18(uint256,uint256) (BondCalculator-flatten.sol#496-527) is never used and should be removed +mulDivSigned(int256,int256,int256) (BondCalculator-flatten.sol#546-583) is never used and should be removed +sqrt(uint256) (BondCalculator-flatten.sol#596-673) is never used and should be removed +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#dead-code + +Notes: by design +INFO:Detectors: +Function BondCalculator.calculateIDF(address,uint256,uint256,uint256,uint256) (BondCalculator-flatten.sol#863-925) contains magic numbers: 3, 3, 3 +Function BondCalculator.calculatePayoutOLAS(address,uint256,uint256,uint256,uint256,uint256,uint256) (BondCalculator-flatten.sol#936-965) contains magic number: 1e36 +Reference: https://github.com/pessimistic-io/slitherin/blob/master/docs/magic_number.md + +Notes: ignore +INFO:Detectors: +Depository.redeem(uint256[]) (Depository-flatten.sol#925-964) ignores return value by IToken(olas).transfer(msg.sender,payout) (Depository-flatten.sol#963) +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-transfer +INFO:Detectors: + +Notes: OK, ref to real issue. +Depository.minOLASLeftoverAmount (Depository-flatten.sol#610) is never initialized. It is used in: + - Depository.deposit(uint256,uint256,uint256) (Depository-flatten.sol#833-915) +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-state-variables + +Notes: False positive. +INFO:Detectors: +Potential vulnerable to readonly-reentrancy function (if read in other function) Depository.getBondStatus(uint256) (Depository-flatten.sol#1053-1059): + State variables read that were written after the external call(s): + - Depository.mapUserBonds (Depository-flatten.sol#622) was read at payout = mapUserBonds[bondId].payout (Depository-flatten.sol#1054) + This variable was written at (after external call): + - mapUserBonds[bondId] = Bond(uint96(payout),uint32(maturity),uint32(productId)) (Depository-flatten.sol#892) + - Depository.mapUserBonds (Depository-flatten.sol#622) was read at payout > 0 (Depository-flatten.sol#1056) + This variable was written at (after external call): + - mapUserBonds[bondId] = Bond(uint96(payout),uint32(maturity),uint32(productId)) (Depository-flatten.sol#892) + - Depository.mapUserBonds (Depository-flatten.sol#622) was read at matured = block.timestamp >= mapUserBonds[bondId].maturity (Depository-flatten.sol#1057) + This variable was written at (after external call): + - mapUserBonds[bondId] = Bond(uint96(payout),uint32(maturity),uint32(productId)) (Depository-flatten.sol#892) + - Depository.mapUserBonds (Depository-flatten.sol#622) was read at END_IF (Depository-flatten.sol#1056-1058) + This variable was written at (after external call): + - mapUserBonds[bondId] = Bond(uint96(payout),uint32(maturity),uint32(productId)) (Depository-flatten.sol#892) +Potential vulnerable to readonly-reentrancy function (if read in other function) Depository.getBonds(address,bool) (Depository-flatten.sol#1008-1047): + State variables read that were written after the external call(s): + - Depository.mapUserBonds (Depository-flatten.sol#622) was read at ! matured || block.timestamp >= mapUserBonds[i].maturity (Depository-flatten.sol#1026-1028) + This variable was written at (after external call): + - mapUserBonds[bondId] = Bond(uint96(payout),uint32(maturity),uint32(productId)) (Depository-flatten.sol#892) + - Depository.mapUserBonds (Depository-flatten.sol#622) was read at positions[i] = true (Depository-flatten.sol#1030) + This variable was written at (after external call): + - mapUserBonds[bondId] = Bond(uint96(payout),uint32(maturity),uint32(productId)) (Depository-flatten.sol#892) + - Depository.mapUserBonds (Depository-flatten.sol#622) was read at ++ numAccountBonds (Depository-flatten.sol#1031) + This variable was written at (after external call): + - mapUserBonds[bondId] = Bond(uint96(payout),uint32(maturity),uint32(productId)) (Depository-flatten.sol#892) + - Depository.mapUserBonds (Depository-flatten.sol#622) was read at payout += mapUserBonds[i].payout (Depository-flatten.sol#1033) + This variable was written at (after external call): + - mapUserBonds[bondId] = Bond(uint96(payout),uint32(maturity),uint32(productId)) (Depository-flatten.sol#892) + - Depository.mapUserBonds (Depository-flatten.sol#622) was read at END_IF (Depository-flatten.sol#1026-1034) + This variable was written at (after external call): + - mapUserBonds[bondId] = Bond(uint96(payout),uint32(maturity),uint32(productId)) (Depository-flatten.sol#892) + - Depository.mapUserBonds (Depository-flatten.sol#622) was read at END_IF (Depository-flatten.sol#1024-1035) + This variable was written at (after external call): + - mapUserBonds[bondId] = Bond(uint96(payout),uint32(maturity),uint32(productId)) (Depository-flatten.sol#892) + - Depository.mapUserBonds (Depository-flatten.sol#622) was read at ++ i (Depository-flatten.sol#1021) + This variable was written at (after external call): + - mapUserBonds[bondId] = Bond(uint96(payout),uint32(maturity),uint32(productId)) (Depository-flatten.sol#892) + - Depository.totalSupply (Depository-flatten.sol#605) was read at numBonds = totalSupply (Depository-flatten.sol#1018) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at positions = new bool[](numBonds) (Depository-flatten.sol#1019) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at BEGIN_LOOP (Depository-flatten.sol#1021-1036) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at END_LOOP (Depository-flatten.sol#1021-1036) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at i = 0 (Depository-flatten.sol#1021) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at i < numBonds (Depository-flatten.sol#1021) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at _ownerOf[i] == account (Depository-flatten.sol#1024) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at ! matured || block.timestamp >= mapUserBonds[i].maturity (Depository-flatten.sol#1026-1028) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at positions[i] = true (Depository-flatten.sol#1030) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at ++ numAccountBonds (Depository-flatten.sol#1031) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at payout += mapUserBonds[i].payout (Depository-flatten.sol#1033) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at END_IF (Depository-flatten.sol#1026-1034) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at END_IF (Depository-flatten.sol#1024-1035) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at ++ i (Depository-flatten.sol#1021) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at bondIds = new uint256[](numAccountBonds) (Depository-flatten.sol#1039) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at NEW VARIABLE numPos (Depository-flatten.sol#1040) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at BEGIN_LOOP (Depository-flatten.sol#1041-1046) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at END_LOOP (Depository-flatten.sol#1041-1046) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at i_scope_0 = 0 (Depository-flatten.sol#1041) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at i_scope_0 < numBonds (Depository-flatten.sol#1041) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at positions[i_scope_0] (Depository-flatten.sol#1042) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at bondIds[numPos] = i_scope_0 (Depository-flatten.sol#1043) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at ++ numPos (Depository-flatten.sol#1044) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at END_IF (Depository-flatten.sol#1042-1045) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at ++ i_scope_0 (Depository-flatten.sol#1041) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) +Potential vulnerable to readonly-reentrancy function (if read in other function) Depository.getProducts(bool) (Depository-flatten.sol#969-992): + State variables read that were written after the external call(s): + - Depository.mapBondProducts (Depository-flatten.sol#624) was read at (active && mapBondProducts[i].supply > 0) || (! active && mapBondProducts[i].supply == 0) (Depository-flatten.sol#977) + This variable was written at (after external call): + - delete mapBondProducts[productId] (Depository-flatten.sol#806) + - mapBondProducts[productId] = Product(uint160(priceLP),uint96(supply),token,0,uint32(vesting)) (Depository-flatten.sol#774) + - delete mapBondProducts[productId] (Depository-flatten.sol#910) + - Depository.mapBondProducts (Depository-flatten.sol#624) was read at positions[i] = true (Depository-flatten.sol#978) + This variable was written at (after external call): + - delete mapBondProducts[productId] (Depository-flatten.sol#806) + - mapBondProducts[productId] = Product(uint160(priceLP),uint96(supply),token,0,uint32(vesting)) (Depository-flatten.sol#774) + - delete mapBondProducts[productId] (Depository-flatten.sol#910) + - Depository.mapBondProducts (Depository-flatten.sol#624) was read at ++ numSelectedProducts (Depository-flatten.sol#979) + This variable was written at (after external call): + - delete mapBondProducts[productId] (Depository-flatten.sol#806) + - mapBondProducts[productId] = Product(uint160(priceLP),uint96(supply),token,0,uint32(vesting)) (Depository-flatten.sol#774) + - delete mapBondProducts[productId] (Depository-flatten.sol#910) + - Depository.mapBondProducts (Depository-flatten.sol#624) was read at END_IF (Depository-flatten.sol#977-980) + This variable was written at (after external call): + - delete mapBondProducts[productId] (Depository-flatten.sol#806) + - mapBondProducts[productId] = Product(uint160(priceLP),uint96(supply),token,0,uint32(vesting)) (Depository-flatten.sol#774) + - delete mapBondProducts[productId] (Depository-flatten.sol#910) + - Depository.mapBondProducts (Depository-flatten.sol#624) was read at ++ i (Depository-flatten.sol#975) + This variable was written at (after external call): + - delete mapBondProducts[productId] (Depository-flatten.sol#806) + - mapBondProducts[productId] = Product(uint160(priceLP),uint96(supply),token,0,uint32(vesting)) (Depository-flatten.sol#774) + - delete mapBondProducts[productId] (Depository-flatten.sol#910) + - Depository.productCounter (Depository-flatten.sol#608) was read at numProducts = productCounter (Depository-flatten.sol#971) + This variable was written at (after external call): + - productCounter = productId + 1 (Depository-flatten.sol#776) + - Depository.productCounter (Depository-flatten.sol#608) was read at positions = new bool[](numProducts) (Depository-flatten.sol#972) + This variable was written at (after external call): + - productCounter = productId + 1 (Depository-flatten.sol#776) + - Depository.productCounter (Depository-flatten.sol#608) was read at NEW VARIABLE numSelectedProducts (Depository-flatten.sol#973) + This variable was written at (after external call): + - productCounter = productId + 1 (Depository-flatten.sol#776) + - Depository.productCounter (Depository-flatten.sol#608) was read at BEGIN_LOOP (Depository-flatten.sol#975-981) + This variable was written at (after external call): + - productCounter = productId + 1 (Depository-flatten.sol#776) + - Depository.productCounter (Depository-flatten.sol#608) was read at END_LOOP (Depository-flatten.sol#975-981) + This variable was written at (after external call): + - productCounter = productId + 1 (Depository-flatten.sol#776) + - Depository.productCounter (Depository-flatten.sol#608) was read at i = 0 (Depository-flatten.sol#975) + This variable was written at (after external call): + - productCounter = productId + 1 (Depository-flatten.sol#776) + - Depository.productCounter (Depository-flatten.sol#608) was read at i < numProducts (Depository-flatten.sol#975) + This variable was written at (after external call): + - productCounter = productId + 1 (Depository-flatten.sol#776) + - Depository.productCounter (Depository-flatten.sol#608) was read at (active && mapBondProducts[i].supply > 0) || (! active && mapBondProducts[i].supply == 0) (Depository-flatten.sol#977) + This variable was written at (after external call): + - productCounter = productId + 1 (Depository-flatten.sol#776) + - Depository.productCounter (Depository-flatten.sol#608) was read at positions[i] = true (Depository-flatten.sol#978) + This variable was written at (after external call): + - productCounter = productId + 1 (Depository-flatten.sol#776) + - Depository.productCounter (Depository-flatten.sol#608) was read at ++ numSelectedProducts (Depository-flatten.sol#979) + This variable was written at (after external call): + - productCounter = productId + 1 (Depository-flatten.sol#776) + - Depository.productCounter (Depository-flatten.sol#608) was read at END_IF (Depository-flatten.sol#977-980) + This variable was written at (after external call): + - productCounter = productId + 1 (Depository-flatten.sol#776) + - Depository.productCounter (Depository-flatten.sol#608) was read at ++ i (Depository-flatten.sol#975) + This variable was written at (after external call): + - productCounter = productId + 1 (Depository-flatten.sol#776) + - Depository.productCounter (Depository-flatten.sol#608) was read at productIds = new uint256[](numSelectedProducts) (Depository-flatten.sol#984) + This variable was written at (after external call): + - productCounter = productId + 1 (Depository-flatten.sol#776) + - Depository.productCounter (Depository-flatten.sol#608) was read at NEW VARIABLE numPos (Depository-flatten.sol#985) + This variable was written at (after external call): + - productCounter = productId + 1 (Depository-flatten.sol#776) + - Depository.productCounter (Depository-flatten.sol#608) was read at BEGIN_LOOP (Depository-flatten.sol#986-991) + This variable was written at (after external call): + - productCounter = productId + 1 (Depository-flatten.sol#776) + - Depository.productCounter (Depository-flatten.sol#608) was read at END_LOOP (Depository-flatten.sol#986-991) + This variable was written at (after external call): + - productCounter = productId + 1 (Depository-flatten.sol#776) + - Depository.productCounter (Depository-flatten.sol#608) was read at i_scope_0 = 0 (Depository-flatten.sol#986) + This variable was written at (after external call): + - productCounter = productId + 1 (Depository-flatten.sol#776) + - Depository.productCounter (Depository-flatten.sol#608) was read at i_scope_0 < numProducts (Depository-flatten.sol#986) + This variable was written at (after external call): + - productCounter = productId + 1 (Depository-flatten.sol#776) + - Depository.productCounter (Depository-flatten.sol#608) was read at positions[i_scope_0] (Depository-flatten.sol#987) + This variable was written at (after external call): + - productCounter = productId + 1 (Depository-flatten.sol#776) + - Depository.productCounter (Depository-flatten.sol#608) was read at productIds[numPos] = i_scope_0 (Depository-flatten.sol#988) + This variable was written at (after external call): + - productCounter = productId + 1 (Depository-flatten.sol#776) + - Depository.productCounter (Depository-flatten.sol#608) was read at ++ numPos (Depository-flatten.sol#989) + This variable was written at (after external call): + - productCounter = productId + 1 (Depository-flatten.sol#776) + - Depository.productCounter (Depository-flatten.sol#608) was read at END_IF (Depository-flatten.sol#987-990) + This variable was written at (after external call): + - productCounter = productId + 1 (Depository-flatten.sol#776) + - Depository.productCounter (Depository-flatten.sol#608) was read at ++ i_scope_0 (Depository-flatten.sol#986) + This variable was written at (after external call): + - productCounter = productId + 1 (Depository-flatten.sol#776) +Potential vulnerable to readonly-reentrancy function (if read in other function) Depository.isActiveProduct(uint256) (Depository-flatten.sol#997-999): + State variables read that were written after the external call(s): + - Depository.mapBondProducts (Depository-flatten.sol#624) was read at status = (mapBondProducts[productId].supply > 0) (Depository-flatten.sol#998) + This variable was written at (after external call): + - delete mapBondProducts[productId] (Depository-flatten.sol#806) + - mapBondProducts[productId] = Product(uint160(priceLP),uint96(supply),token,0,uint32(vesting)) (Depository-flatten.sol#774) + - delete mapBondProducts[productId] (Depository-flatten.sol#910) +Potential vulnerable to readonly-reentrancy function (if read in other function) Depository.tokenByIndex(uint256) (Depository-flatten.sol#1071-1077): + State variables read that were written after the external call(s): + - Depository.totalSupply (Depository-flatten.sol#605) was read at id >= totalSupply (Depository-flatten.sol#1072) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at revert Overflow(uint256,uint256)(id,totalSupply - 1) (Depository-flatten.sol#1073) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at END_IF (Depository-flatten.sol#1072-1074) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + - Depository.totalSupply (Depository-flatten.sol#605) was read at id (Depository-flatten.sol#1076) + This variable was written at (after external call): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) +Reference: https://github.com/pessimistic-io/slitherin/blob/master/docs/readonly_reentrancy.md + +Notes: False positive +INFO:Detectors: +IToken (Depository-flatten.sol#136-175) has incorrect ERC721 function interface:IToken.approve(address,uint256) (Depository-flatten.sol#167) +IToken (Depository-flatten.sol#136-175) has incorrect ERC721 function interface:IToken.transferFrom(address,address,uint256) (Depository-flatten.sol#174) +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc721-interface + +Notes: False positive +INFO:Detectors: +Depository.redeem(uint256[]) (Depository-flatten.sol#925-964) uses a dangerous strict equality: + - pay == 0 || ! matured (Depository-flatten.sol#932) +Depository.redeem(uint256[]) (Depository-flatten.sol#925-964) uses a dangerous strict equality: + - payout == 0 (Depository-flatten.sol#957) +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-strict-equalities + +Notes: False positive +INFO:Detectors: +Reentrancy in Depository.close(uint256[]) (Depository-flatten.sol#786-819): + External calls: + - ITokenomics(tokenomics).refundFromBondProgram(supply) (Depository-flatten.sol#804) + State variables written after the call(s): + - delete mapBondProducts[productId] (Depository-flatten.sol#806) + Depository.mapBondProducts (Depository-flatten.sol#624) can be used in cross function reentrancies: + - Depository.close(uint256[]) (Depository-flatten.sol#786-819) + - Depository.create(address,uint256,uint256,uint256) (Depository-flatten.sol#725-778) + - Depository.deposit(uint256,uint256,uint256) (Depository-flatten.sol#833-915) + - Depository.getProducts(bool) (Depository-flatten.sol#969-992) + - Depository.isActiveProduct(uint256) (Depository-flatten.sol#997-999) + - Depository.mapBondProducts (Depository-flatten.sol#624) + +Notes: OK, real siiue +Reentrancy in Depository.deposit(uint256,uint256,uint256) (Depository-flatten.sol#833-915): + External calls: + - _safeMint(msg.sender,bondId) (Depository-flatten.sol#891) + - require(bool,string)(ERC721TokenReceiver(to).onERC721Received(msg.sender,address(0),id,) == ERC721TokenReceiver.onERC721Received.selector,UNSAFE_RECIPIENT) (Depository-flatten.sol#461-465) + State variables written after the call(s): + - totalSupply = bondId + 1 (Depository-flatten.sol#895) + Depository.totalSupply (Depository-flatten.sol#605) can be used in cross function reentrancies: + - Depository.deposit(uint256,uint256,uint256) (Depository-flatten.sol#833-915) + - Depository.getBonds(address,bool) (Depository-flatten.sol#1008-1047) + - Depository.tokenByIndex(uint256) (Depository-flatten.sol#1071-1077) + - Depository.totalSupply (Depository-flatten.sol#605) +Reentrancy in Depository.deposit(uint256,uint256,uint256) (Depository-flatten.sol#833-915): + External calls: + - _safeMint(msg.sender,bondId) (Depository-flatten.sol#891) + - require(bool,string)(ERC721TokenReceiver(to).onERC721Received(msg.sender,address(0),id,) == ERC721TokenReceiver.onERC721Received.selector,UNSAFE_RECIPIENT) (Depository-flatten.sol#461-465) + - ITreasury(treasury).depositTokenForOLAS(msg.sender,tokenAmount,token,payout) (Depository-flatten.sol#899) + State variables written after the call(s): + - delete mapBondProducts[productId] (Depository-flatten.sol#910) + Depository.mapBondProducts (Depository-flatten.sol#624) can be used in cross function reentrancies: + - Depository.close(uint256[]) (Depository-flatten.sol#786-819) + - Depository.create(address,uint256,uint256,uint256) (Depository-flatten.sol#725-778) + - Depository.deposit(uint256,uint256,uint256) (Depository-flatten.sol#833-915) + - Depository.getProducts(bool) (Depository-flatten.sol#969-992) + - Depository.isActiveProduct(uint256) (Depository-flatten.sol#997-999) + - Depository.mapBondProducts (Depository-flatten.sol#624) +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-1 + +Notes: ignore +INFO:Detectors: +Depository.getProducts(bool).numSelectedProducts (Depository-flatten.sol#973) is a local variable never initialized +Depository.getBonds(address,bool).numPos (Depository-flatten.sol#1040) is a local variable never initialized +Depository.getProducts(bool).numPos (Depository-flatten.sol#985) is a local variable never initialized +Depository.getBonds(address,bool).numAccountBonds (Depository-flatten.sol#1016) is a local variable never initialized +Depository.close(uint256[]).numClosedProducts (Depository-flatten.sol#795) is a local variable never initialized +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-local-variables + +Notes: Ignore +INFO:Detectors: +Dubious typecast in Depository.create(address,uint256,uint256,uint256) (Depository-flatten.sol#725-778): + uint256 => uint160 casting occurs in mapBondProducts[productId] = Product(uint160(priceLP),uint96(supply),token,0,uint32(vesting)) (Depository-flatten.sol#774) + uint256 => uint96 casting occurs in mapBondProducts[productId] = Product(uint160(priceLP),uint96(supply),token,0,uint32(vesting)) (Depository-flatten.sol#774) + uint256 => uint32 casting occurs in mapBondProducts[productId] = Product(uint160(priceLP),uint96(supply),token,0,uint32(vesting)) (Depository-flatten.sol#774) +Dubious typecast in Depository.deposit(uint256,uint256,uint256) (Depository-flatten.sol#833-915): + uint256 => uint96 casting occurs in product.supply = uint96(supply) (Depository-flatten.sol#885) + uint256 => uint96 casting occurs in product.payout += uint96(payout) (Depository-flatten.sol#886) + uint256 => uint96 casting occurs in mapUserBonds[bondId] = Bond(uint96(payout),uint32(maturity),uint32(productId)) (Depository-flatten.sol#892) + uint256 => uint32 casting occurs in mapUserBonds[bondId] = Bond(uint96(payout),uint32(maturity),uint32(productId)) (Depository-flatten.sol#892) + uint256 => uint32 casting occurs in mapUserBonds[bondId] = Bond(uint96(payout),uint32(maturity),uint32(productId)) (Depository-flatten.sol#892) +Reference: https://github.com/pessimistic-io/slitherin/blob/master/docs/dubious_typecast.md + +Notes: by design +INFO:Detectors: +Depository.close(uint256[]) (Depository-flatten.sol#786-819) has external calls inside a loop: ITokenomics(tokenomics).refundFromBondProgram(supply) (Depository-flatten.sol#804) +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation/#calls-inside-a-loop + +Notes: False positive +INFO:Detectors: +Reentrancy in Depository.create(address,uint256,uint256,uint256) (Depository-flatten.sol#725-778): + External calls: + - ! ITokenomics(tokenomics).reserveAmountForBondProgram(supply) (Depository-flatten.sol#768) + State variables written after the call(s): + - mapBondProducts[productId] = Product(uint160(priceLP),uint96(supply),token,0,uint32(vesting)) (Depository-flatten.sol#774) + - productCounter = productId + 1 (Depository-flatten.sol#776) +Notes: correct +Reentrancy in Depository.deposit(uint256,uint256,uint256) (Depository-flatten.sol#833-915): + External calls: + - _safeMint(msg.sender,bondId) (Depository-flatten.sol#891) + - require(bool,string)(ERC721TokenReceiver(to).onERC721Received(msg.sender,address(0),id,) == ERC721TokenReceiver.onERC721Received.selector,UNSAFE_RECIPIENT) (Depository-flatten.sol#461-465) + State variables written after the call(s): + - mapUserBonds[bondId] = Bond(uint96(payout),uint32(maturity),uint32(productId)) (Depository-flatten.sol#892) +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-2 +Notes: Ignore +INFO:Detectors: +Reentrancy in Depository.close(uint256[]) (Depository-flatten.sol#786-819): + External calls: + - ITokenomics(tokenomics).refundFromBondProgram(supply) (Depository-flatten.sol#804) + Event emitted after the call(s): + - CloseProduct(token,productId,supply) (Depository-flatten.sol#810) +Notes: Ignore +Reentrancy in Depository.create(address,uint256,uint256,uint256) (Depository-flatten.sol#725-778): + External calls: + - ! ITokenomics(tokenomics).reserveAmountForBondProgram(supply) (Depository-flatten.sol#768) + Event emitted after the call(s): + - CreateProduct(token,productId,supply,priceLP,vesting) (Depository-flatten.sol#777) +Notes: Correct +Reentrancy in Depository.deposit(uint256,uint256,uint256) (Depository-flatten.sol#833-915): + External calls: + - _safeMint(msg.sender,bondId) (Depository-flatten.sol#891) + - require(bool,string)(ERC721TokenReceiver(to).onERC721Received(msg.sender,address(0),id,) == ERC721TokenReceiver.onERC721Received.selector,UNSAFE_RECIPIENT) (Depository-flatten.sol#461-465) + - ITreasury(treasury).depositTokenForOLAS(msg.sender,tokenAmount,token,payout) (Depository-flatten.sol#899) + Event emitted after the call(s): + - CloseProduct(token,productId,supply) (Depository-flatten.sol#911) + - CreateBond(token,productId,msg.sender,bondId,payout,tokenAmount,maturity) (Depository-flatten.sol#914) +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-3 +Notes: ignore +INFO:Detectors: +Depository.create(address,uint256,uint256,uint256) (Depository-flatten.sol#725-778) uses timestamp for comparisons + Dangerous comparisons: + - maturity > type()(uint32).max (Depository-flatten.sol#758) +Depository.deposit(uint256,uint256,uint256) (Depository-flatten.sol#833-915) uses timestamp for comparisons + Dangerous comparisons: + - maturity > type()(uint32).max (Depository-flatten.sol#861) +Depository.redeem(uint256[]) (Depository-flatten.sol#925-964) uses timestamp for comparisons + Dangerous comparisons: + - matured = block.timestamp >= mapUserBonds[bondIds[i]].maturity (Depository-flatten.sol#929) + - pay == 0 || ! matured (Depository-flatten.sol#932) + - payout == 0 (Depository-flatten.sol#957) +Depository.getBonds(address,bool) (Depository-flatten.sol#1008-1047) uses timestamp for comparisons + Dangerous comparisons: + - ! matured || block.timestamp >= mapUserBonds[i].maturity (Depository-flatten.sol#1026-1028) +Depository.getBondStatus(uint256) (Depository-flatten.sol#1053-1059) uses timestamp for comparisons + Dangerous comparisons: + - payout > 0 (Depository-flatten.sol#1056) + - matured = block.timestamp >= mapUserBonds[bondId].maturity (Depository-flatten.sol#1057) +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#block-timestamp +Notes: ignore +INFO:Detectors: +Depository.close(uint256[]) (Depository-flatten.sol#786-819) has costly operations inside a loop: + - delete mapBondProducts[productId] (Depository-flatten.sol#806) +ERC721._burn(uint256) (Depository-flatten.sol#436-451) has costly operations inside a loop: + - delete _ownerOf[id] (Depository-flatten.sol#446) +ERC721._burn(uint256) (Depository-flatten.sol#436-451) has costly operations inside a loop: + - delete getApproved[id] (Depository-flatten.sol#448) +Depository.redeem(uint256[]) (Depository-flatten.sol#925-964) has costly operations inside a loop: + - delete mapUserBonds[bondIds[i]] (Depository-flatten.sol#952) +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#costly-operations-inside-a-loop +Notes: ignore +INFO:Detectors: +ERC721._safeMint(address,uint256,bytes) (Depository-flatten.sol#468-481) is never used and should be removed +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#dead-code +Notes: ignore +INFO:Detectors: +Variable ERC721._ownerOf (Depository-flatten.sol#295) is not in mixedCase +Variable ERC721._balanceOf (Depository-flatten.sol#297) is not in mixedCase +Parameter Depository.changeManagers(address,address)._tokenomics (Depository-flatten.sol#685) is not in mixedCase +Parameter Depository.changeManagers(address,address)._treasury (Depository-flatten.sol#685) is not in mixedCase +Parameter Depository.changeBondCalculator(address)._bondCalculator (Depository-flatten.sol#705) is not in mixedCase +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#conformance-to-solidity-naming-conventions +Notes: incorrect +INFO:Detectors: +Depository.minOLASLeftoverAmount (Depository-flatten.sol#610) should be constant +Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-constant +Notes: ignore +INFO:Detectors: +In a function Depository.close(uint256[]) (Depository-flatten.sol#786-819) variable Depository.mapBondProducts (Depository-flatten.sol#624) is read multiple times +In a function Depository.redeem(uint256[]) (Depository-flatten.sol#925-964) variable Depository.mapUserBonds (Depository-flatten.sol#622) is read multiple times +Reference: https://github.com/pessimistic-io/slitherin/blob/master/docs/multiple_storage_read.md + diff --git a/audits/internal6/analysis/slither_function-summary.txt b/audits/internal6/analysis/slither_function-summary.txt new file mode 100644 index 00000000..812095b1 --- /dev/null +++ b/audits/internal6/analysis/slither_function-summary.txt @@ -0,0 +1,314 @@ +'solc --version' running +'solc ./BondCalculator-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +'solc --version' running +'solc ./Depository-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +Compilation warnings/errors on ./Depository-flatten.sol: +Warning: This declaration shadows an existing declaration. + --> Depository-flatten.sol:84:5: + | +84 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Note: The shadowed declaration is here: + --> Depository-flatten.sol:528:1: + | +528 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +INFO:Printers: +Contract IUniswapV2Pair +Contract vars: [] +Inheritance:: [] + ++---------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ +| Function | Visibility | Modifiers | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++---------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ +| totalSupply() | external | [] | [] | [] | [] | [] | 2 | +| token0() | external | [] | [] | [] | [] | [] | 2 | +| token1() | external | [] | [] | [] | [] | [] | 2 | +| getReserves() | external | [] | [] | [] | [] | [] | 2 | ++---------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ + ++-----------+------------+------+-------+----------------+----------------+-----------------------+ +| Modifiers | Visibility | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++-----------+------------+------+-------+----------------+----------------+-----------------------+ ++-----------+------------+------+-------+----------------+----------------+-----------------------+ + +INFO:Printers: +Contract IVotingEscrow +Contract vars: [] +Inheritance:: [] + ++-------------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ +| Function | Visibility | Modifiers | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++-------------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ +| getVotes(address) | external | [] | [] | [] | [] | [] | 2 | ++-------------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ + ++-----------+------------+------+-------+----------------+----------------+-----------------------+ +| Modifiers | Visibility | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++-----------+------------+------+-------+----------------+----------------+-----------------------+ ++-----------+------------+------+-------+----------------+----------------+-----------------------+ + +INFO:Printers: +Contract ITokenomics +Contract vars: [] +Inheritance:: [] + ++---------------------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ +| Function | Visibility | Modifiers | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++---------------------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ +| getLastEpochNumNewUnits() | external | [] | [] | [] | [] | [] | 2 | ++---------------------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ + ++-----------+------------+------+-------+----------------+----------------+-----------------------+ +| Modifiers | Visibility | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++-----------+------------+------+-------+----------------+----------------+-----------------------+ ++-----------+------------+------+-------+----------------+----------------+-----------------------+ + +INFO:Printers: +Contract BondCalculator +Contract vars: ['MAX_SUM_WEIGHTS', 'olas', 'tokenomics', 've', 'owner', 'discountParams'] +Inheritance:: [] + ++------------------------------------------------------------------------------+------------+-----------+---------------------------------------+----------------------------+---------------------------------------------------------------------------+----------------------------------------------------------------------------------------------+-----------------------+ +| Function | Visibility | Modifiers | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++------------------------------------------------------------------------------+------------+-----------+---------------------------------------+----------------------------+---------------------------------------------------------------------------+----------------------------------------------------------------------------------------------+-----------------------+ +| constructor(address,address,address,DiscountParams) | public | [] | ['MAX_SUM_WEIGHTS', 'msg.sender'] | ['discountParams', 'olas'] | ['revert Overflow(uint256,uint256)', 'revert ZeroAddress()'] | [] | 5 | +| | | | | ['owner', 'tokenomics'] | ['revert ZeroValue()'] | | | +| | | | | ['ve'] | | | | +| changeOwner(address) | external | [] | ['msg.sender', 'owner'] | ['owner'] | ['revert OwnerOnly(address,address)', 'revert ZeroAddress()'] | [] | 3 | +| changeDiscountParams(DiscountParams) | external | [] | ['MAX_SUM_WEIGHTS', 'msg.sender'] | ['discountParams'] | ['revert Overflow(uint256,uint256)', 'revert OwnerOnly(address,address)'] | [] | 5 | +| | | | ['owner'] | | ['revert ZeroValue()'] | | | +| calculateIDF(address,uint256,uint256,uint256,uint256) | public | [] | ['MAX_SUM_WEIGHTS', 'discountParams'] | [] | [] | ['ITokenomics(tokenomics).getLastEpochNumNewUnits()', 'IVotingEscrow(ve).getVotes(account)'] | 9 | +| | | | ['tokenomics', 've'] | | | | | +| calculatePayoutOLAS(address,uint256,uint256,uint256,uint256,uint256,uint256) | external | [] | [] | [] | ['calculateIDF', 'mulDiv'] | [] | 2 | +| | | | | | ['revert Overflow(uint256,uint256)'] | | | +| getCurrentPriceLP(address) | external | [] | ['olas'] | [] | [] | ['pair.getReserves()', 'pair.token0()'] | 4 | +| | | | | | | ['pair.token1()', 'pair.totalSupply()'] | | +| getDiscountParams() | external | [] | ['discountParams'] | [] | [] | [] | 1 | +| slitherConstructorConstantVariables() | internal | [] | [] | ['MAX_SUM_WEIGHTS'] | [] | [] | 1 | ++------------------------------------------------------------------------------+------------+-----------+---------------------------------------+----------------------------+---------------------------------------------------------------------------+----------------------------------------------------------------------------------------------+-----------------------+ + ++-----------+------------+------+-------+----------------+----------------+-----------------------+ +| Modifiers | Visibility | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++-----------+------------+------+-------+----------------+----------------+-----------------------+ ++-----------+------------+------+-------+----------------+----------------+-----------------------+ + +INFO:Printers: +Contract IErrorsTokenomics +Contract vars: [] +Inheritance:: [] + ++----------+------------+-----------+------+-------+----------------+----------------+-----------------------+ +| Function | Visibility | Modifiers | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++----------+------------+-----------+------+-------+----------------+----------------+-----------------------+ ++----------+------------+-----------+------+-------+----------------+----------------+-----------------------+ + ++-----------+------------+------+-------+----------------+----------------+-----------------------+ +| Modifiers | Visibility | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++-----------+------------+------+-------+----------------+----------------+-----------------------+ ++-----------+------------+------+-------+----------------+----------------+-----------------------+ + +INFO:Printers: +Contract IToken +Contract vars: [] +Inheritance:: [] + ++---------------------------------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ +| Function | Visibility | Modifiers | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++---------------------------------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ +| balanceOf(address) | external | [] | [] | [] | [] | [] | 2 | +| ownerOf(uint256) | external | [] | [] | [] | [] | [] | 2 | +| totalSupply() | external | [] | [] | [] | [] | [] | 2 | +| transfer(address,uint256) | external | [] | [] | [] | [] | [] | 2 | +| allowance(address,address) | external | [] | [] | [] | [] | [] | 2 | +| approve(address,uint256) | external | [] | [] | [] | [] | [] | 2 | +| transferFrom(address,address,uint256) | external | [] | [] | [] | [] | [] | 2 | ++---------------------------------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ + ++-----------+------------+------+-------+----------------+----------------+-----------------------+ +| Modifiers | Visibility | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++-----------+------------+------+-------+----------------+----------------+-----------------------+ ++-----------+------------+------+-------+----------------+----------------+-----------------------+ + +INFO:Printers: +Contract ITokenomics +Contract vars: [] +Inheritance:: [] + ++------------------------------------------------------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ +| Function | Visibility | Modifiers | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++------------------------------------------------------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ +| effectiveBond() | external | [] | [] | [] | [] | [] | 2 | +| checkpoint() | external | [] | [] | [] | [] | [] | 2 | +| trackServiceDonations(address,uint256[],uint256[],uint256) | external | [] | [] | [] | [] | [] | 2 | +| reserveAmountForBondProgram(uint256) | external | [] | [] | [] | [] | [] | 2 | +| refundFromBondProgram(uint256) | external | [] | [] | [] | [] | [] | 2 | +| accountOwnerIncentives(address,uint256[],uint256[]) | external | [] | [] | [] | [] | [] | 2 | +| getLastIDF() | external | [] | [] | [] | [] | [] | 2 | +| serviceRegistry() | external | [] | [] | [] | [] | [] | 2 | ++------------------------------------------------------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ + ++-----------+------------+------+-------+----------------+----------------+-----------------------+ +| Modifiers | Visibility | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++-----------+------------+------+-------+----------------+----------------+-----------------------+ ++-----------+------------+------+-------+----------------+----------------+-----------------------+ + +INFO:Printers: +Contract ITreasury +Contract vars: [] +Inheritance:: [] + ++------------------------------------------------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ +| Function | Visibility | Modifiers | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++------------------------------------------------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ +| depositTokenForOLAS(address,uint256,address,uint256) | external | [] | [] | [] | [] | [] | 2 | +| depositServiceDonationsETH(uint256[],uint256[]) | external | [] | [] | [] | [] | [] | 2 | +| isEnabled(address) | external | [] | [] | [] | [] | [] | 2 | +| withdrawToAccount(address,uint256,uint256) | external | [] | [] | [] | [] | [] | 2 | +| rebalanceTreasury(uint256) | external | [] | [] | [] | [] | [] | 2 | ++------------------------------------------------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ + ++-----------+------------+------+-------+----------------+----------------+-----------------------+ +| Modifiers | Visibility | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++-----------+------------+------+-------+----------------+----------------+-----------------------+ ++-----------+------------+------+-------+----------------+----------------+-----------------------+ + +INFO:Printers: +Contract ERC721 +Contract vars: ['name', 'symbol', '_ownerOf', '_balanceOf', 'getApproved', 'isApprovedForAll'] +Inheritance:: [] + ++-------------------------------------------------+------------+-----------+-------------------------------------+----------------------------+-------------------------------------------+-----------------------------------------------------------------------------+-----------------------+ +| Function | Visibility | Modifiers | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++-------------------------------------------------+------------+-----------+-------------------------------------+----------------------------+-------------------------------------------+-----------------------------------------------------------------------------+-----------------------+ +| tokenURI(uint256) | public | [] | [] | [] | [] | [] | 2 | +| ownerOf(uint256) | public | [] | ['_ownerOf'] | [] | ['require(bool,string)'] | [] | 1 | +| balanceOf(address) | public | [] | ['_balanceOf'] | [] | ['require(bool,string)'] | [] | 1 | +| constructor(string,string) | internal | [] | [] | ['name', 'symbol'] | [] | [] | 1 | +| approve(address,uint256) | public | [] | ['_ownerOf', 'isApprovedForAll'] | ['getApproved'] | ['require(bool,string)'] | [] | 1 | +| | | | ['msg.sender'] | | | | | +| setApprovalForAll(address,bool) | public | [] | ['msg.sender'] | ['isApprovedForAll'] | [] | [] | 1 | +| transferFrom(address,address,uint256) | public | [] | ['_balanceOf', '_ownerOf'] | ['_balanceOf', '_ownerOf'] | ['require(bool,string)'] | [] | 1 | +| | | | ['getApproved', 'isApprovedForAll'] | ['getApproved'] | | | | +| | | | ['msg.sender'] | | | | | +| safeTransferFrom(address,address,uint256) | public | [] | ['msg.sender'] | [] | ['code(address)', 'require(bool,string)'] | ['ERC721TokenReceiver(to).onERC721Received(msg.sender,from,id,)'] | 2 | +| | | | | | ['transferFrom'] | | | +| safeTransferFrom(address,address,uint256,bytes) | public | [] | ['msg.sender'] | [] | ['code(address)', 'require(bool,string)'] | ['ERC721TokenReceiver(to).onERC721Received(msg.sender,from,id,data)'] | 2 | +| | | | | | ['transferFrom'] | | | +| supportsInterface(bytes4) | public | [] | [] | [] | [] | [] | 1 | +| _mint(address,uint256) | internal | [] | ['_balanceOf', '_ownerOf'] | ['_balanceOf', '_ownerOf'] | ['require(bool,string)'] | [] | 1 | +| _burn(uint256) | internal | [] | ['_balanceOf', '_ownerOf'] | ['_balanceOf', '_ownerOf'] | ['require(bool,string)'] | [] | 1 | +| | | | ['getApproved'] | ['getApproved'] | | | | +| _safeMint(address,uint256) | internal | [] | ['msg.sender'] | [] | ['_mint', 'code(address)'] | ['ERC721TokenReceiver(to).onERC721Received(msg.sender,address(0),id,)'] | 2 | +| | | | | | ['require(bool,string)'] | | | +| _safeMint(address,uint256,bytes) | internal | [] | ['msg.sender'] | [] | ['_mint', 'code(address)'] | ['ERC721TokenReceiver(to).onERC721Received(msg.sender,address(0),id,data)'] | 2 | +| | | | | | ['require(bool,string)'] | | | ++-------------------------------------------------+------------+-----------+-------------------------------------+----------------------------+-------------------------------------------+-----------------------------------------------------------------------------+-----------------------+ + ++-----------+------------+------+-------+----------------+----------------+-----------------------+ +| Modifiers | Visibility | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++-----------+------------+------+-------+----------------+----------------+-----------------------+ ++-----------+------------+------+-------+----------------+----------------+-----------------------+ + +INFO:Printers: +Contract ERC721TokenReceiver +Contract vars: [] +Inheritance:: [] + ++-------------------------------------------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ +| Function | Visibility | Modifiers | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++-------------------------------------------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ +| onERC721Received(address,address,uint256,bytes) | external | [] | [] | [] | [] | [] | 1 | ++-------------------------------------------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ + ++-----------+------------+------+-------+----------------+----------------+-----------------------+ +| Modifiers | Visibility | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++-----------+------------+------+-------+----------------+----------------+-----------------------+ ++-----------+------------+------+-------+----------------+----------------+-----------------------+ + +INFO:Printers: +Contract IBondCalculator +Contract vars: [] +Inheritance:: [] + ++------------------------------------------------------------------------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ +| Function | Visibility | Modifiers | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++------------------------------------------------------------------------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ +| calculatePayoutOLAS(address,uint256,uint256,uint256,uint256,uint256,uint256) | external | [] | [] | [] | [] | [] | 2 | +| getCurrentPriceLP(address) | external | [] | [] | [] | [] | [] | 2 | ++------------------------------------------------------------------------------+------------+-----------+------+-------+----------------+----------------+-----------------------+ + ++-----------+------------+------+-------+----------------+----------------+-----------------------+ +| Modifiers | Visibility | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++-----------+------------+------+-------+----------------+----------------+-----------------------+ ++-----------+------------+------+-------+----------------+----------------+-----------------------+ + +INFO:Printers: +Contract Depository +Contract vars: ['name', 'symbol', '_ownerOf', '_balanceOf', 'getApproved', 'isApprovedForAll', 'MIN_VESTING', 'VERSION', 'baseURI', 'owner', 'totalSupply', 'productCounter', 'minOLASLeftoverAmount', 'olas', 'tokenomics', 'treasury', 'bondCalculator', 'mapUserBonds', 'mapBondProducts'] +Inheritance:: ['IErrorsTokenomics', 'ERC721'] + ++-------------------------------------------------------------------+------------+-----------+-----------------------------------------+---------------------------------------+-----------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------+ +| Function | Visibility | Modifiers | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++-------------------------------------------------------------------+------------+-----------+-----------------------------------------+---------------------------------------+-----------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------+ +| tokenURI(uint256) | public | [] | [] | [] | [] | [] | 2 | +| ownerOf(uint256) | public | [] | ['_ownerOf'] | [] | ['require(bool,string)'] | [] | 1 | +| balanceOf(address) | public | [] | ['_balanceOf'] | [] | ['require(bool,string)'] | [] | 1 | +| constructor(string,string) | internal | [] | [] | ['name', 'symbol'] | [] | [] | 1 | +| approve(address,uint256) | public | [] | ['_ownerOf', 'isApprovedForAll'] | ['getApproved'] | ['require(bool,string)'] | [] | 1 | +| | | | ['msg.sender'] | | | | | +| setApprovalForAll(address,bool) | public | [] | ['msg.sender'] | ['isApprovedForAll'] | [] | [] | 1 | +| transferFrom(address,address,uint256) | public | [] | ['_balanceOf', '_ownerOf'] | ['_balanceOf', '_ownerOf'] | ['require(bool,string)'] | [] | 1 | +| | | | ['getApproved', 'isApprovedForAll'] | ['getApproved'] | | | | +| | | | ['msg.sender'] | | | | | +| safeTransferFrom(address,address,uint256) | public | [] | ['msg.sender'] | [] | ['code(address)', 'require(bool,string)'] | ['ERC721TokenReceiver(to).onERC721Received(msg.sender,from,id,)'] | 2 | +| | | | | | ['transferFrom'] | | | +| safeTransferFrom(address,address,uint256,bytes) | public | [] | ['msg.sender'] | [] | ['code(address)', 'require(bool,string)'] | ['ERC721TokenReceiver(to).onERC721Received(msg.sender,from,id,data)'] | 2 | +| | | | | | ['transferFrom'] | | | +| supportsInterface(bytes4) | public | [] | [] | [] | [] | [] | 1 | +| _mint(address,uint256) | internal | [] | ['_balanceOf', '_ownerOf'] | ['_balanceOf', '_ownerOf'] | ['require(bool,string)'] | [] | 1 | +| _burn(uint256) | internal | [] | ['_balanceOf', '_ownerOf'] | ['_balanceOf', '_ownerOf'] | ['require(bool,string)'] | [] | 1 | +| | | | ['getApproved'] | ['getApproved'] | | | | +| _safeMint(address,uint256) | internal | [] | ['msg.sender'] | [] | ['_mint', 'code(address)'] | ['ERC721TokenReceiver(to).onERC721Received(msg.sender,address(0),id,)'] | 2 | +| | | | | | ['require(bool,string)'] | | | +| _safeMint(address,uint256,bytes) | internal | [] | ['msg.sender'] | [] | ['_mint', 'code(address)'] | ['ERC721TokenReceiver(to).onERC721Received(msg.sender,address(0),id,data)'] | 2 | +| | | | | | ['require(bool,string)'] | | | +| constructor(string,string,string,address,address,address,address) | public | [] | ['msg.sender'] | ['baseURI', 'bondCalculator'] | ['constructor', 'revert ZeroAddress()'] | [] | 3 | +| | | | | ['olas', 'owner'] | ['revert ZeroValue()'] | | | +| | | | | ['tokenomics', 'treasury'] | | | | +| changeOwner(address) | external | [] | ['msg.sender', 'owner'] | ['owner'] | ['revert OwnerOnly(address,address)', 'revert ZeroAddress()'] | [] | 3 | +| changeManagers(address,address) | external | [] | ['msg.sender', 'owner'] | ['tokenomics', 'treasury'] | ['revert OwnerOnly(address,address)'] | [] | 4 | +| changeBondCalculator(address) | external | [] | ['msg.sender', 'owner'] | ['bondCalculator'] | ['revert OwnerOnly(address,address)'] | [] | 3 | +| create(address,uint256,uint256,uint256) | external | [] | ['MIN_VESTING', 'block.timestamp'] | ['mapBondProducts', 'productCounter'] | ['revert LowerThan(uint256,uint256)', 'revert Overflow(uint256,uint256)'] | ['ITokenomics(tokenomics).effectiveBond()', 'ITokenomics(tokenomics).reserveAmountForBondProgram(supply)'] | 10 | +| | | | ['msg.sender', 'owner'] | | ['revert OwnerOnly(address,address)', 'revert UnauthorizedToken(address)'] | ['ITreasury(treasury).isEnabled(token)'] | | +| | | | ['productCounter', 'tokenomics'] | | ['revert ZeroValue()'] | | | +| | | | ['treasury'] | | | | | +| close(uint256[]) | external | [] | ['mapBondProducts', 'msg.sender'] | ['mapBondProducts'] | ['revert OwnerOnly(address,address)'] | ['ITokenomics(tokenomics).refundFromBondProgram(supply)', 'new uint256[](numClosedProducts)'] | 5 | +| | | | ['owner', 'tokenomics'] | | | ['new uint256[](numProducts)'] | | +| deposit(uint256,uint256,uint256) | external | [] | ['MIN_VESTING', 'block.timestamp'] | ['mapBondProducts', 'mapUserBonds'] | ['_safeMint', 'revert LowerThan(uint256,uint256)'] | ['IBondCalculator(bondCalculator).calculatePayoutOLAS(msg.sender,tokenAmount,product.priceLP,bondVestingTime,productMaxVestingTime,supply,product.payout)', 'IToken(olas).balanceOf(address(this))'] | 10 | +| | | | ['bondCalculator', 'mapBondProducts'] | ['totalSupply'] | ['revert Overflow(uint256,uint256)', 'revert ProductClosed(uint256)'] | ['IToken(olas).balanceOf(address(this))', 'ITreasury(treasury).depositTokenForOLAS(msg.sender,tokenAmount,token,payout)'] | | +| | | | ['minOLASLeftoverAmount', 'msg.sender'] | | ['revert ProductSupplyLow(address,uint256,uint256,uint256)', 'revert WrongAmount(uint256,uint256)'] | | | +| | | | ['olas', 'this'] | | ['revert ZeroValue()'] | | | +| | | | ['totalSupply', 'treasury'] | | | | | +| redeem(uint256[]) | external | [] | ['_ownerOf', 'block.timestamp'] | ['mapUserBonds'] | ['_burn', 'revert BondNotRedeemable(uint256)'] | ['IToken(olas).transfer(msg.sender,payout)'] | 5 | +| | | | ['mapUserBonds', 'msg.sender'] | | ['revert OwnerOnly(address,address)', 'revert ZeroValue()'] | | | +| | | | ['olas'] | | | | | +| getProducts(bool) | external | [] | ['mapBondProducts', 'productCounter'] | [] | [] | ['new bool[](numProducts)', 'new uint256[](numSelectedProducts)'] | 5 | +| isActiveProduct(uint256) | external | [] | ['mapBondProducts'] | [] | [] | [] | 1 | +| getBonds(address,bool) | external | [] | ['_ownerOf', 'block.timestamp'] | [] | ['revert ZeroAddress()'] | ['new bool[](numBonds)', 'new uint256[](numAccountBonds)'] | 7 | +| | | | ['mapUserBonds', 'totalSupply'] | | | | | +| getBondStatus(uint256) | external | [] | ['block.timestamp', 'mapUserBonds'] | [] | [] | [] | 2 | +| getCurrentPriceLP(address) | external | [] | ['bondCalculator'] | [] | [] | ['IBondCalculator(bondCalculator).getCurrentPriceLP(token)'] | 1 | +| tokenByIndex(uint256) | external | [] | ['totalSupply'] | [] | ['revert Overflow(uint256,uint256)'] | [] | 2 | +| tokenURI(uint256) | public | [] | ['baseURI'] | [] | ['abi.encodePacked()'] | ['abi.encodePacked(baseURI,bondId)'] | 1 | +| slitherConstructorConstantVariables() | internal | [] | [] | ['MIN_VESTING', 'VERSION'] | [] | [] | 1 | ++-------------------------------------------------------------------+------------+-----------+-----------------------------------------+---------------------------------------+-----------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------+ + ++-----------+------------+------+-------+----------------+----------------+-----------------------+ +| Modifiers | Visibility | Read | Write | Internal Calls | External Calls | Cyclomatic Complexity | ++-----------+------------+------+-------+----------------+----------------+-----------------------+ ++-----------+------------+------+-------+----------------+----------------+-----------------------+ + +INFO:Slither:. analyzed (12 contracts) diff --git a/audits/internal6/analysis/slither_human-summary.txt b/audits/internal6/analysis/slither_human-summary.txt new file mode 100644 index 00000000..9a1f7b24 --- /dev/null +++ b/audits/internal6/analysis/slither_human-summary.txt @@ -0,0 +1,62 @@ +'solc --version' running +'solc ./BondCalculator-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +'solc --version' running +'solc ./Depository-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +Compilation warnings/errors on ./Depository-flatten.sol: +Warning: This declaration shadows an existing declaration. + --> Depository-flatten.sol:84:5: + | +84 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Note: The shadowed declaration is here: + --> Depository-flatten.sol:528:1: + | +528 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +INFO:Printers: +Compiled with solc +Total number of contracts in source files: 4 +Source lines of code (SLOC) in source files: 572 +Number of assembly lines: 0 +Number of optimization issues: 0 +Number of informational issues: 10 +Number of low issues: 0 +Number of medium issues: 2 +Number of high issues: 0 + + ++----------------+-------------+------+------------+--------------+----------+ +| Name | # functions | ERCS | ERC20 info | Complex code | Features | ++----------------+-------------+------+------------+--------------+----------+ +| IUniswapV2Pair | 4 | | | No | | +| IVotingEscrow | 1 | | | No | | +| ITokenomics | 1 | | | No | | +| BondCalculator | 8 | | | Yes | | ++----------------+-------------+------+------------+--------------+----------+ +INFO:Printers: +Compiled with solc +Total number of contracts in source files: 8 +Source lines of code (SLOC) in source files: 505 +Number of assembly lines: 0 +Number of optimization issues: 3 +Number of informational issues: 12 +Number of low issues: 11 +Number of medium issues: 14 +Number of high issues: 7 +ERCs: ERC721, ERC165, ERC20 + ++---------------------+-------------+---------------+--------------------+--------------+--------------------+ +| Name | # functions | ERCS | ERC20 info | Complex code | Features | ++---------------------+-------------+---------------+--------------------+--------------+--------------------+ +| IToken | 7 | ERC20 | No Minting | No | | +| | | | Approve Race Cond. | | | +| | | | | | | +| ITokenomics | 8 | | | No | | +| ITreasury | 5 | | | No | Receive ETH | +| ERC721TokenReceiver | 1 | | | No | | +| IBondCalculator | 2 | | | No | | +| Depository | 30 | ERC165,ERC721 | | Yes | Tokens interaction | ++---------------------+-------------+---------------+--------------------+--------------+--------------------+ +INFO:Slither:. analyzed (12 contracts) diff --git a/audits/internal6/analysis/slither_inheritance-graph.txt b/audits/internal6/analysis/slither_inheritance-graph.txt new file mode 100644 index 00000000..daac0e74 --- /dev/null +++ b/audits/internal6/analysis/slither_inheritance-graph.txt @@ -0,0 +1,22 @@ +'solc --version' running +'solc ./BondCalculator-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +'solc --version' running +'solc ./Depository-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +Compilation warnings/errors on ./Depository-flatten.sol: +Warning: This declaration shadows an existing declaration. + --> Depository-flatten.sol:84:5: + | +84 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Note: The shadowed declaration is here: + --> Depository-flatten.sol:528:1: + | +528 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +INFO:Printers:Inheritance Graph: ./BondCalculator-flatten.sol.inheritance-graph.dot + +INFO:Printers:Inheritance Graph: ./Depository-flatten.sol.inheritance-graph.dot + +INFO:Slither:. analyzed (12 contracts) diff --git a/audits/internal6/analysis/slither_inheritance.txt b/audits/internal6/analysis/slither_inheritance.txt new file mode 100644 index 00000000..4044977c --- /dev/null +++ b/audits/internal6/analysis/slither_inheritance.txt @@ -0,0 +1,81 @@ +'solc --version' running +'solc ./BondCalculator-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +'solc --version' running +'solc ./Depository-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +Compilation warnings/errors on ./Depository-flatten.sol: +Warning: This declaration shadows an existing declaration. + --> Depository-flatten.sol:84:5: + | +84 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Note: The shadowed declaration is here: + --> Depository-flatten.sol:528:1: + | +528 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +INFO:Printers:Inheritance +Child_Contract -> Immediate_Base_Contracts [Not_Immediate_Base_Contracts] ++ IUniswapV2Pair + ++ IVotingEscrow + ++ ITokenomics + ++ BondCalculator + + +Base_Contract -> Immediate_Child_Contracts + [Not_Immediate_Child_Contracts] + ++ IUniswapV2Pair + ++ IVotingEscrow + ++ ITokenomics + ++ BondCalculator + +INFO:Printers:Inheritance +Child_Contract -> Immediate_Base_Contracts [Not_Immediate_Base_Contracts] ++ IErrorsTokenomics + ++ IToken + ++ ITokenomics + ++ ITreasury + ++ ERC721 + ++ ERC721TokenReceiver + ++ IBondCalculator + ++ Depository + -> ERC721, IErrorsTokenomics + + +Base_Contract -> Immediate_Child_Contracts + [Not_Immediate_Child_Contracts] + ++ IErrorsTokenomics + -> Depository + ++ IToken + ++ ITokenomics + ++ ITreasury + ++ ERC721 + -> Depository + ++ ERC721TokenReceiver + ++ IBondCalculator + ++ Depository + +INFO:Slither:. analyzed (12 contracts) diff --git a/audits/internal6/analysis/slither_modifiers.txt b/audits/internal6/analysis/slither_modifiers.txt new file mode 100644 index 00000000..4b07b8ca --- /dev/null +++ b/audits/internal6/analysis/slither_modifiers.txt @@ -0,0 +1,145 @@ +'solc --version' running +'solc ./BondCalculator-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +'solc --version' running +'solc ./Depository-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +Compilation warnings/errors on ./Depository-flatten.sol: +Warning: This declaration shadows an existing declaration. + --> Depository-flatten.sol:84:5: + | +84 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Note: The shadowed declaration is here: + --> Depository-flatten.sol:528:1: + | +528 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +INFO:Printers: +Contract IUniswapV2Pair ++-------------+-----------+ +| Function | Modifiers | ++-------------+-----------+ +| totalSupply | [] | +| token0 | [] | +| token1 | [] | +| getReserves | [] | ++-------------+-----------+ +INFO:Printers: +Contract IVotingEscrow ++----------+-----------+ +| Function | Modifiers | ++----------+-----------+ +| getVotes | [] | ++----------+-----------+ +INFO:Printers: +Contract ITokenomics ++-------------------------+-----------+ +| Function | Modifiers | ++-------------------------+-----------+ +| getLastEpochNumNewUnits | [] | ++-------------------------+-----------+ +INFO:Printers: +Contract BondCalculator ++-------------------------------------+-----------+ +| Function | Modifiers | ++-------------------------------------+-----------+ +| constructor | [] | +| changeOwner | [] | +| changeDiscountParams | [] | +| calculateIDF | [] | +| calculatePayoutOLAS | [] | +| getCurrentPriceLP | [] | +| getDiscountParams | [] | +| slitherConstructorConstantVariables | [] | ++-------------------------------------+-----------+ +INFO:Printers: +Contract IToken ++--------------+-----------+ +| Function | Modifiers | ++--------------+-----------+ +| balanceOf | [] | +| ownerOf | [] | +| totalSupply | [] | +| transfer | [] | +| allowance | [] | +| approve | [] | +| transferFrom | [] | ++--------------+-----------+ +INFO:Printers: +Contract ITokenomics ++-----------------------------+-----------+ +| Function | Modifiers | ++-----------------------------+-----------+ +| effectiveBond | [] | +| checkpoint | [] | +| trackServiceDonations | [] | +| reserveAmountForBondProgram | [] | +| refundFromBondProgram | [] | +| accountOwnerIncentives | [] | +| getLastIDF | [] | +| serviceRegistry | [] | ++-----------------------------+-----------+ +INFO:Printers: +Contract ITreasury ++----------------------------+-----------+ +| Function | Modifiers | ++----------------------------+-----------+ +| depositTokenForOLAS | [] | +| depositServiceDonationsETH | [] | +| isEnabled | [] | +| withdrawToAccount | [] | +| rebalanceTreasury | [] | ++----------------------------+-----------+ +INFO:Printers: +Contract ERC721TokenReceiver ++------------------+-----------+ +| Function | Modifiers | ++------------------+-----------+ +| onERC721Received | [] | ++------------------+-----------+ +INFO:Printers: +Contract IBondCalculator ++---------------------+-----------+ +| Function | Modifiers | ++---------------------+-----------+ +| calculatePayoutOLAS | [] | +| getCurrentPriceLP | [] | ++---------------------+-----------+ +INFO:Printers: +Contract Depository ++-------------------------------------+-----------+ +| Function | Modifiers | ++-------------------------------------+-----------+ +| tokenURI | [] | +| ownerOf | [] | +| balanceOf | [] | +| constructor | [] | +| approve | [] | +| setApprovalForAll | [] | +| transferFrom | [] | +| safeTransferFrom | [] | +| safeTransferFrom | [] | +| supportsInterface | [] | +| _mint | [] | +| _burn | [] | +| _safeMint | [] | +| _safeMint | [] | +| constructor | [] | +| changeOwner | [] | +| changeManagers | [] | +| changeBondCalculator | [] | +| create | [] | +| close | [] | +| deposit | [] | +| redeem | [] | +| getProducts | [] | +| isActiveProduct | [] | +| getBonds | [] | +| getBondStatus | [] | +| getCurrentPriceLP | [] | +| tokenByIndex | [] | +| tokenURI | [] | +| slitherConstructorConstantVariables | [] | ++-------------------------------------+-----------+ +INFO:Slither:. analyzed (12 contracts) diff --git a/audits/internal6/analysis/slither_require.txt b/audits/internal6/analysis/slither_require.txt new file mode 100644 index 00000000..9697ae23 --- /dev/null +++ b/audits/internal6/analysis/slither_require.txt @@ -0,0 +1,160 @@ +'solc --version' running +'solc ./BondCalculator-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +'solc --version' running +'solc ./Depository-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +Compilation warnings/errors on ./Depository-flatten.sol: +Warning: This declaration shadows an existing declaration. + --> Depository-flatten.sol:84:5: + | +84 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Note: The shadowed declaration is here: + --> Depository-flatten.sol:528:1: + | +528 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +INFO:Printers: +Contract IUniswapV2Pair ++-------------+-------------------+ +| Function | require or assert | ++-------------+-------------------+ +| totalSupply | | +| token0 | | +| token1 | | +| getReserves | | ++-------------+-------------------+ +INFO:Printers: +Contract IVotingEscrow ++----------+-------------------+ +| Function | require or assert | ++----------+-------------------+ +| getVotes | | ++----------+-------------------+ +INFO:Printers: +Contract ITokenomics ++-------------------------+-------------------+ +| Function | require or assert | ++-------------------------+-------------------+ +| getLastEpochNumNewUnits | | ++-------------------------+-------------------+ +INFO:Printers: +Contract BondCalculator ++-------------------------------------+-------------------+ +| Function | require or assert | ++-------------------------------------+-------------------+ +| constructor | | +| changeOwner | | +| changeDiscountParams | | +| calculateIDF | | +| calculatePayoutOLAS | | +| getCurrentPriceLP | | +| getDiscountParams | | +| slitherConstructorConstantVariables | | ++-------------------------------------+-------------------+ +INFO:Printers: +Contract IToken ++--------------+-------------------+ +| Function | require or assert | ++--------------+-------------------+ +| balanceOf | | +| ownerOf | | +| totalSupply | | +| transfer | | +| allowance | | +| approve | | +| transferFrom | | ++--------------+-------------------+ +INFO:Printers: +Contract ITokenomics ++-----------------------------+-------------------+ +| Function | require or assert | ++-----------------------------+-------------------+ +| effectiveBond | | +| checkpoint | | +| trackServiceDonations | | +| reserveAmountForBondProgram | | +| refundFromBondProgram | | +| accountOwnerIncentives | | +| getLastIDF | | +| serviceRegistry | | ++-----------------------------+-------------------+ +INFO:Printers: +Contract ITreasury ++----------------------------+-------------------+ +| Function | require or assert | ++----------------------------+-------------------+ +| depositTokenForOLAS | | +| depositServiceDonationsETH | | +| isEnabled | | +| withdrawToAccount | | +| rebalanceTreasury | | ++----------------------------+-------------------+ +INFO:Printers: +Contract ERC721TokenReceiver ++------------------+-------------------+ +| Function | require or assert | ++------------------+-------------------+ +| onERC721Received | | ++------------------+-------------------+ +INFO:Printers: +Contract IBondCalculator ++---------------------+-------------------+ +| Function | require or assert | ++---------------------+-------------------+ +| calculatePayoutOLAS | | +| getCurrentPriceLP | | ++---------------------+-------------------+ +INFO:Printers: +Contract Depository ++-------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Function | require or assert | ++-------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| tokenURI | | +| ownerOf | require(bool,string)((owner = _ownerOf[id]) != address(0),NOT_MINTED) | +| balanceOf | require(bool,string)(owner != address(0),ZERO_ADDRESS) | +| constructor | | +| approve | require(bool,string)(msg.sender == owner || isApprovedForAll[owner][msg.sender],NOT_AUTHORIZED) | +| setApprovalForAll | | +| transferFrom | require(bool,string)(from == _ownerOf[id],WRONG_FROM) | +| | require(bool,string)(msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],NOT_AUTHORIZED) | +| | require(bool,string)(to != address(0),INVALID_RECIPIENT) | +| safeTransferFrom | require(bool,string)(ERC721TokenReceiver(to).onERC721Received(msg.sender,from,id,) == ERC721TokenReceiver.onERC721Received.selector,UNSAFE_RECIPIENT) | +| | require(bool,string)(from == _ownerOf[id],WRONG_FROM) | +| | require(bool,string)(msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],NOT_AUTHORIZED) | +| | require(bool,string)(to != address(0),INVALID_RECIPIENT) | +| safeTransferFrom | require(bool,string)(ERC721TokenReceiver(to).onERC721Received(msg.sender,from,id,data) == ERC721TokenReceiver.onERC721Received.selector,UNSAFE_RECIPIENT) | +| | require(bool,string)(from == _ownerOf[id],WRONG_FROM) | +| | require(bool,string)(msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],NOT_AUTHORIZED) | +| | require(bool,string)(to != address(0),INVALID_RECIPIENT) | +| supportsInterface | | +| _mint | require(bool,string)(_ownerOf[id] == address(0),ALREADY_MINTED) | +| | require(bool,string)(to != address(0),INVALID_RECIPIENT) | +| _burn | require(bool,string)(owner != address(0),NOT_MINTED) | +| _safeMint | require(bool,string)(ERC721TokenReceiver(to).onERC721Received(msg.sender,address(0),id,) == ERC721TokenReceiver.onERC721Received.selector,UNSAFE_RECIPIENT) | +| | require(bool,string)(_ownerOf[id] == address(0),ALREADY_MINTED) | +| | require(bool,string)(to != address(0),INVALID_RECIPIENT) | +| _safeMint | require(bool,string)(ERC721TokenReceiver(to).onERC721Received(msg.sender,address(0),id,data) == ERC721TokenReceiver.onERC721Received.selector,UNSAFE_RECIPIENT) | +| | require(bool,string)(_ownerOf[id] == address(0),ALREADY_MINTED) | +| | require(bool,string)(to != address(0),INVALID_RECIPIENT) | +| constructor | | +| changeOwner | | +| changeManagers | | +| changeBondCalculator | | +| create | | +| close | | +| deposit | require(bool,string)(ERC721TokenReceiver(to).onERC721Received(msg.sender,address(0),id,) == ERC721TokenReceiver.onERC721Received.selector,UNSAFE_RECIPIENT) | +| | require(bool,string)(_ownerOf[id] == address(0),ALREADY_MINTED) | +| | require(bool,string)(to != address(0),INVALID_RECIPIENT) | +| redeem | require(bool,string)(owner != address(0),NOT_MINTED) | +| getProducts | | +| isActiveProduct | | +| getBonds | | +| getBondStatus | | +| getCurrentPriceLP | | +| tokenByIndex | | +| tokenURI | | +| slitherConstructorConstantVariables | | ++-------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+ +INFO:Slither:. analyzed (12 contracts) diff --git a/audits/internal6/analysis/slither_variable-order.txt b/audits/internal6/analysis/slither_variable-order.txt new file mode 100644 index 00000000..1b8d9631 --- /dev/null +++ b/audits/internal6/analysis/slither_variable-order.txt @@ -0,0 +1,98 @@ +'solc --version' running +'solc ./BondCalculator-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +'solc --version' running +'solc ./Depository-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +Compilation warnings/errors on ./Depository-flatten.sol: +Warning: This declaration shadows an existing declaration. + --> Depository-flatten.sol:84:5: + | +84 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Note: The shadowed declaration is here: + --> Depository-flatten.sol:528:1: + | +528 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +INFO:Printers: +IUniswapV2Pair: ++------+------+------+--------+ +| Name | Type | Slot | Offset | ++------+------+------+--------+ ++------+------+------+--------+ + +IVotingEscrow: ++------+------+------+--------+ +| Name | Type | Slot | Offset | ++------+------+------+--------+ ++------+------+------+--------+ + +ITokenomics: ++------+------+------+--------+ +| Name | Type | Slot | Offset | ++------+------+------+--------+ ++------+------+------+--------+ + +BondCalculator: ++-------------------------------+----------------+------+--------+ +| Name | Type | Slot | Offset | ++-------------------------------+----------------+------+--------+ +| BondCalculator.owner | address | 0 | 0 | +| BondCalculator.discountParams | DiscountParams | 1 | 0 | ++-------------------------------+----------------+------+--------+ + +INFO:Printers: +IToken: ++------+------+-----[96m-+--------+ +| Name | Type | Slot | Offset | ++------+------+------+--------+ ++------+------+------+--------+ + +ITokenomics: ++------+------+------+--------+ +| Name | Type | Slot | Offset | ++------+------+------+--------+ ++------+------+------+--------+ + +ITreasury: ++------+------+------+--------+ +| Name | Type | Slot | Offset | ++------+------+------+--------+ ++------+------+------+--------+ + +ERC721TokenReceiver: ++------+------+------+--------+ +| Name | Type | Slot | Offset | ++------+------+------+--------+ ++------+------+------+--------+ + +IBondCalculator: ++------+------+------+--------+ +| Name | Type | Slot | Offset | ++------+------+------+--------+ ++------+------+------+--------+ + +Depository: ++----------------------------------+----------------------------------------------+------+--------+ +| Name | Type | Slot | Offset | ++----------------------------------+----------------------------------------------+------+--------+ +| ERC721.name | string | 0 | 0 | +| ERC721.symbol | string | 1 | 0 | +| ERC721._ownerOf | mapping(uint256 => address) | 2 | 0 | +| ERC721._balanceOf | mapping(address => uint256) | 3 | 0 | +| ERC721.getApproved | mapping(uint256 => address) | 4 | 0 | +| ERC721.isApprovedForAll | mapping(address => mapping(address => bool)) | 5 | 0 | +| Depository.baseURI | string | 6 | 0 | +| Depository.owner | address | 7 | 0 | +| Depository.totalSupply | uint256 | 8 | 0 | +| Depository.productCounter | uint256 | 9 | 0 | +| Depository.minOLASLeftoverAmount | uint256 | 10 | 0 | +| Depository.tokenomics | address | 11 | 0 | +| Depository.treasury | address | 12 | 0 | +| Depository.bondCalculator | address | 13 | 0 | +| Depository.mapUserBonds | mapping(uint256 => Bond) | 14 | 0 | +| Depository.mapBondProducts | mapping(uint256 => Product) | 15 | 0 | ++----------------------------------+----------------------------------------------+------+--------+ + +INFO:Slither:. analyzed (12 contracts) diff --git a/audits/internal6/analysis/slither_vars-and-auth.txt b/audits/internal6/analysis/slither_vars-and-auth.txt new file mode 100644 index 00000000..c2d9f0ff --- /dev/null +++ b/audits/internal6/analysis/slither_vars-and-auth.txt @@ -0,0 +1,173 @@ +'solc --version' running +'solc ./BondCalculator-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +'solc --version' running +'solc ./Depository-flatten.sol --combined-json abi,ast,bin,bin-runtime,srcmap,srcmap-runtime,userdoc,devdoc,hashes --allow-paths .,/home/andrey/valory/autonolas-tokenomics/audits/internal5/analysis/contracts' running +Compilation warnings/errors on ./Depository-flatten.sol: +Warning: This declaration shadows an existing declaration. + --> Depository-flatten.sol:84:5: + | +84 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Note: The shadowed declaration is here: + --> Depository-flatten.sol:528:1: + | +528 | error WrongAmount(uint256 provided, uint256 expected); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +INFO:Printers: +Contract IUniswapV2Pair ++-------------+-------------------------+--------------------------+ +| Function | State variables written | Conditions on msg.sender | ++-------------+-------------------------+--------------------------+ +| totalSupply | [] | [] | +| token0 | [] | [] | +| token1 | [] | [] | +| getReserves | [] | [] | ++-------------+-------------------------+--------------------------+ + +Contract IVotingEscrow ++----------+-------------------------+--------------------------+ +| Function | State variables written | Conditions on msg.sender | ++----------+-------------------------+--------------------------+ +| getVotes | [] | [] | ++----------+-------------------------+--------------------------+ + +Contract ITokenomics ++-------------------------+-------------------------+--------------------------+ +| Function | State variables written | Conditions on msg.sender | ++-------------------------+-------------------------+--------------------------+ +| getLastEpochNumNewUnits | [] | [] | ++-------------------------+-------------------------+--------------------------+ + +Contract BondCalculator ++-------------------------------------+---------------------------------------------------------+--------------------------+ +| Function | State variables written | Conditions on msg.sender | ++-------------------------------------+---------------------------------------------------------+--------------------------+ +| constructor | ['discountParams', 'olas', 'owner', 'tokenomics', 've'] | [] | +| changeOwner | ['owner'] | ['msg.sender != owner'] | +| changeDiscountParams | ['discountParams'] | ['msg.sender != owner'] | +| calculateIDF | [] | [] | +| calculatePayoutOLAS | [] | [] | +| getCurrentPriceLP | [] | [] | +| getDiscountParams | [] | [] | +| slitherConstructorConstantVariables | ['MAX_SUM_WEIGHTS'] | [] | ++-------------------------------------+---------------------------------------------------------+--------------------------+ + +INFO:Printers: +Contract IErrorsTokenomics ++----------+-------------------------+--------------------------+ +| Function | State variables written | Conditions on msg.sender | ++----------+-------------------------+--------------------------+ ++----------+-------------------------+--------------------------+ + +Contract IToken ++--------------+-------------------------+--------------------------+ +| Function | State variables written | Conditions on msg.sender | ++--------------+-------------------------+--------------------------+ +| balanceOf | [] | [] | +| ownerOf | [] | [] | +| totalSupply | [] | [] | +| transfer | [] | [] | +| allowance | [] | [] | +| approve | [] | [] | +| transferFrom | [] | [] | ++--------------+-------------------------+--------------------------+ + +Contract ITokenomics ++-----------------------------+-------------------------+--------------------------+ +| Function | State variables written | Conditions on msg.sender | ++-----------------------------+-------------------------+--------------------------+ +| effectiveBond | [] | [] | +| checkpoint | [] | [] | +| trackServiceDonations | [] | [] | +| reserveAmountForBondProgram | [] | [] | +| refundFromBondProgram | [] | [] | +| accountOwnerIncentives | [] | [] | +| getLastIDF | [] | [] | +| serviceRegistry | [] | [] | ++-----------------------------+-------------------------+--------------------------+ + +Contract ITreasury ++----------------------------+-------------------------+--------------------------+ +| Function | State variables written | Conditions on msg.sender | ++----------------------------+-------------------------+--------------------------+ +| depositTokenForOLAS | [] | [] | +| depositServiceDonationsETH | [] | [] | +| isEnabled | [] | [] | +| withdrawToAccount | [] | [] | +| rebalanceTreasury | [] | [] | ++----------------------------+-------------------------+--------------------------+ + +Contract ERC721 ++-------------------+-------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Function | State variables written | Conditions on msg.sender | ++-------------------+-------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| tokenURI | [] | [] | +| ownerOf | [] | [] | +| balanceOf | [] | [] | +| constructor | ['name', 'symbol'] | [] | +| approve | ['getApproved'] | ['require(bool,string)(msg.sender == owner || isApprovedForAll[owner][msg.sender],NOT_AUTHORIZED)'] | +| setApprovalForAll | ['isApprovedForAll'] | [] | +| transferFrom | ['_balanceOf', '_ownerOf', 'getApproved'] | ['require(bool,string)(msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],NOT_AUTHORIZED)'] | +| safeTransferFrom | ['_balanceOf', '_ownerOf', 'getApproved'] | ['require(bool,string)(ERC721TokenReceiver(to).onERC721Received(msg.sender,from,id,) == ERC721TokenReceiver.onERC721Received.selector,UNSAFE_RECIPIENT)', 'require(bool,string)(msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],NOT_AUTHORIZED)'] | +| safeTransferFrom | ['_balanceOf', '_ownerOf', 'getApproved'] | ['require(bool,string)(ERC721TokenReceiver(to).onERC721Received(msg.sender,from,id,data) == ERC721TokenReceiver.onERC721Received.selector,UNSAFE_RECIPIENT)', 'require(bool,string)(msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],NOT_AUTHORIZED)'] | +| supportsInterface | [] | [] | +| _mint | ['_balanceOf', '_ownerOf'] | [] | +| _burn | ['_balanceOf', '_ownerOf', 'getApproved'] | [] | +| _safeMint | ['_balanceOf', '_ownerOf'] | ['require(bool,string)(ERC721TokenReceiver(to).onERC721Received(msg.sender,address(0),id,) == ERC721TokenReceiver.onERC721Received.selector,UNSAFE_RECIPIENT)'] | +| _safeMint | ['_balanceOf', '_ownerOf'] | ['require(bool,string)(ERC721TokenReceiver(to).onERC721Received(msg.sender,address(0),id,data) == ERC721TokenReceiver.onERC721Received.selector,UNSAFE_RECIPIENT)'] | ++-------------------+-------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +Contract ERC721TokenReceiver ++------------------+-------------------------+--------------------------+ +| Function | State variables written | Conditions on msg.sender | ++------------------+-------------------------+--------------------------+ +| onERC721Received | [] | [] | ++------------------+-------------------------+--------------------------+ + +Contract IBondCalculator ++---------------------+-------------------------+--------------------------+ +| Function | State variables written | Conditions on msg.sender | ++---------------------+-------------------------+--------------------------+ +| calculatePayoutOLAS | [] | [] | +| getCurrentPriceLP | [] | [] | ++---------------------+-------------------------+--------------------------+ + +Contract Depository ++-------------------------------------+--------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Function | State variables written | Conditions on msg.sender | ++-------------------------------------+--------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| tokenURI | [] | [] | +| ownerOf | [] | [] | +| balanceOf | [] | [] | +| constructor | ['name', 'symbol'] | [] | +| approve | ['getApproved'] | ['require(bool,string)(msg.sender == owner || isApprovedForAll[owner][msg.sender],NOT_AUTHORIZED)'] | +| setApprovalForAll | ['isApprovedForAll'] | [] | +| transferFrom | ['_balanceOf', '_ownerOf', 'getApproved'] | ['require(bool,string)(msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],NOT_AUTHORIZED)'] | +| safeTransferFrom | ['_balanceOf', '_ownerOf', 'getApproved'] | ['require(bool,string)(ERC721TokenReceiver(to).onERC721Received(msg.sender,from,id,) == ERC721TokenReceiver.onERC721Received.selector,UNSAFE_RECIPIENT)', 'require(bool,string)(msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],NOT_AUTHORIZED)'] | +| safeTransferFrom | ['_balanceOf', '_ownerOf', 'getApproved'] | ['require(bool,string)(ERC721TokenReceiver(to).onERC721Received(msg.sender,from,id,data) == ERC721TokenReceiver.onERC721Received.selector,UNSAFE_RECIPIENT)', 'require(bool,string)(msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],NOT_AUTHORIZED)'] | +| supportsInterface | [] | [] | +| _mint | ['_balanceOf', '_ownerOf'] | [] | +| _burn | ['_balanceOf', '_ownerOf', 'getApproved'] | [] | +| _safeMint | ['_balanceOf', '_ownerOf'] | ['require(bool,string)(ERC721TokenReceiver(to).onERC721Received(msg.sender,address(0),id,) == ERC721TokenReceiver.onERC721Received.selector,UNSAFE_RECIPIENT)'] | +| _safeMint | ['_balanceOf', '_ownerOf'] | ['require(bool,string)(ERC721TokenReceiver(to).onERC721Received(msg.sender,address(0),id,data) == ERC721TokenReceiver.onERC721Received.selector,UNSAFE_RECIPIENT)'] | +| constructor | ['baseURI', 'bondCalculator', 'name', 'olas', 'owner', 'symbol', 'tokenomics', 'treasury'] | [] | +| changeOwner | ['owner'] | ['msg.sender != owner'] | +| changeManagers | ['tokenomics', 'treasury'] | ['msg.sender != owner'] | +| changeBondCalculator | ['bondCalculator'] | ['msg.sender != owner'] | +| create | ['mapBondProducts', 'productCounter'] | ['msg.sender != owner'] | +| close | ['mapBondProducts'] | ['msg.sender != owner'] | +| deposit | ['_balanceOf', '_ownerOf', 'mapBondProducts', 'mapUserBonds', 'totalSupply'] | ['require(bool,string)(ERC721TokenReceiver(to).onERC721Received(msg.sender,address(0),id,) == ERC721TokenReceiver.onERC721Received.selector,UNSAFE_RECIPIENT)'] | +| redeem | ['_balanceOf', '_ownerOf', 'getApproved', 'mapUserBonds'] | ['bondOwner != msg.sender'] | +| getProducts | [] | [] | +| isActiveProduct | [] | [] | +| getBonds | [] | [] | +| getBondStatus | [] | [] | +| getCurrentPriceLP | [] | [] | +| tokenByIndex | [] | [] | +| tokenURI | [] | [] | +| slitherConstructorConstantVariables | ['MIN_VESTING', 'VERSION'] | [] | ++-------------------------------------+--------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +INFO:Slither:. analyzed (12 contracts) diff --git a/audits/internal6/analysis/storage/Tokenomics.png b/audits/internal6/analysis/storage/Tokenomics.png new file mode 100644 index 00000000..754e86cd Binary files /dev/null and b/audits/internal6/analysis/storage/Tokenomics.png differ diff --git a/contracts/Depository.sol b/contracts/Depository.sol index f18559fc..e6a86c9b 100644 --- a/contracts/Depository.sol +++ b/contracts/Depository.sol @@ -128,6 +128,8 @@ contract Depository is ERC721, IErrorsTokenomics { address public treasury; // Bond Calculator contract address address public bondCalculator; + // Reentrancy lock + uint8 internal _locked; // Mapping of bond Id => account bond instance mapping(uint256 => Bond) public mapUserBonds; @@ -225,6 +227,17 @@ contract Depository is ERC721, IErrorsTokenomics { } } + /// @dev Sets minimum OLAS leftover amount for the product to keep the supply. + /// @param _minOLASLeftoverAmount Updated minimum OLAS leftover amount. + function setMinOLASLeftoverAmount(uint256 _minOLASLeftoverAmount) external { + // Check for the contract ownership + if (msg.sender != owner) { + revert OwnerOnly(msg.sender, owner); + } + + minOLASLeftoverAmount = _minOLASLeftoverAmount; + } + /// @dev Creates a new bond product. /// @param token LP token to be deposited for pairs like OLAS-DAI, OLAS-ETH, etc. /// @param priceLP LP token price with 18 additional decimals. @@ -344,6 +357,12 @@ contract Depository is ERC721, IErrorsTokenomics { function deposit(uint256 productId, uint256 tokenAmount, uint256 bondVestingTime) external returns (uint256 payout, uint256 maturity, uint256 bondId) { + // Reentrancy guard + if (_locked > 1) { + revert ReentrancyGuard(); + } + _locked = 2; + // Check the token amount if (tokenAmount == 0) { revert ZeroValue(); @@ -423,6 +442,8 @@ contract Depository is ERC721, IErrorsTokenomics { } emit CreateBond(token, productId, msg.sender, bondId, payout, tokenAmount, maturity); + + _locked = 1; } /// @dev Redeems account bonds. diff --git a/contracts/Dispenser.sol b/contracts/Dispenser.sol index 6b10797e..8d869a2f 100644 --- a/contracts/Dispenser.sol +++ b/contracts/Dispenser.sol @@ -267,13 +267,18 @@ contract Dispenser { event TreasuryUpdated(address indexed treasury); event VoteWeightingUpdated(address indexed voteWeighting); event StakingParamsUpdated(uint256 maxNumClaimingEpochs, uint256 maxNumStakingTargets); - event IncentivesClaimed(address indexed owner, uint256 reward, uint256 topUp); - event StakingIncentivesClaimed(address indexed account, uint256 stakingIncentive, uint256 transferAmount, - uint256 returnAmount); + event IncentivesClaimed(address indexed owner, uint256 reward, uint256 topUp, uint256[] unitTypes, uint256[] unitIds); + event StakingIncentivesClaimed(address indexed account, uint256 chainId, bytes32 stakingTarget, + uint256 stakingIncentive, uint256 transferAmount, uint256 returnAmount); + event StakingIncentivesBatchClaimed(address indexed account, uint256[] chainIds, bytes32[][] stakingTargets, + uint256[][] stakingIncentives, uint256 totalStakingIncentive, uint256 totalTransferAmount, + uint256 totalReturnAmount); event Retained(address indexed account, uint256 returnAmount); event SetDepositProcessorChainIds(address[] depositProcessors, uint256[] chainIds); event WithheldAmountSynced(uint256 chainId, uint256 amount, uint256 updatedWithheldAmount, bytes32 indexed batchHash); event PauseDispenser(Pause pauseState); + event AddNomineeHash(bytes32 indexed nomineeHash); + event RemoveNomineeHash(bytes32 indexed nomineeHash); // Maximum chain Id as per EVM specs uint256 public constant MAX_EVM_CHAIN_ID = type(uint64).max / 2 - 36; @@ -397,11 +402,11 @@ contract Dispenser { revert Overflow(firstClaimedEpoch, eCounter - 1); } - // Get epoch when the nominee was removed + // Get epoch number when the nominee was removed uint256 epochRemoved = mapRemovedNomineeEpochs[nomineeHash]; - // If the nominee is not removed, its value in the map is always zero, unless removed + // If the nominee is not removed, its value in the map is always zero // The staking contract nominee cannot be removed in the zero-th epoch by default - if (epochRemoved > 1 && firstClaimedEpoch >= epochRemoved) { + if (epochRemoved > 0 && firstClaimedEpoch >= epochRemoved) { revert Overflow(firstClaimedEpoch, epochRemoved - 1); } @@ -410,7 +415,7 @@ contract Dispenser { // Limit last claimed epoch by the number following the nominee removal epoch // The condition for is lastClaimedEpoch strictly > because the lastClaimedEpoch is not included in claiming - if (epochRemoved > 1 && lastClaimedEpoch > epochRemoved) { + if (epochRemoved > 0 && lastClaimedEpoch > epochRemoved) { lastClaimedEpoch = epochRemoved; } @@ -487,6 +492,11 @@ contract Dispenser { } } + // Skip if there are no actual staking targets + if (numActualTargets == 0) { + continue; + } + // Allocate updated arrays accounting only for nonzero staking incentives bytes32[] memory updatedStakingTargets = new bytes32[](numActualTargets); uint256[] memory updatedStakingAmounts = new uint256[](numActualTargets); @@ -769,9 +779,17 @@ contract Dispenser { } mapLastClaimedStakingEpochs[nomineeHash] = ITokenomics(tokenomics).epochCounter(); + + emit AddNomineeHash(nomineeHash); } /// @dev Records nominee removal epoch number. + /// @notice The staking contract nominee cannot be removed starting from one week before the end of epoch. + /// Since the epoch end time is unknown and the nominee removal is applied in the following week, + /// it is prohibited to remove nominee one week before the foreseen epoch end to correctly reflect + /// the removal epoch number. + /// If the staking contract nominee must not get incentives in the ongoing ending epoch as well, + /// the DAO is advised to use the removeInstance() function in the corresponding StakingFactory contract. /// @param nomineeHash Nominee hash. function removeNominee(bytes32 nomineeHash) external { // Check for the contract ownership @@ -803,6 +821,8 @@ contract Dispenser { // Set the removed nominee epoch number mapRemovedNomineeEpochs[nomineeHash] = eCounter; + + emit RemoveNomineeHash(nomineeHash); } /// @dev Claims incentives for the owner of components / agents. @@ -857,7 +877,7 @@ contract Dispenser { revert ClaimIncentivesFailed(msg.sender, reward, topUp); } - emit IncentivesClaimed(msg.sender, reward, topUp); + emit IncentivesClaimed(msg.sender, reward, topUp, unitTypes, unitIds); _locked = 1; } @@ -1097,7 +1117,7 @@ contract Dispenser { _distributeStakingIncentives(chainId, stakingTarget, stakingIncentive, bridgePayload, transferAmount); } - emit StakingIncentivesClaimed(msg.sender, stakingIncentive, transferAmount, returnAmount); + emit StakingIncentivesClaimed(msg.sender, chainId, stakingTarget, stakingIncentive, transferAmount, returnAmount); _locked = 1; } @@ -1176,7 +1196,8 @@ contract Dispenser { valueAmounts); } - emit StakingIncentivesClaimed(msg.sender, totalAmounts[0], totalAmounts[1], totalAmounts[2]); + emit StakingIncentivesBatchClaimed(msg.sender, chainIds, stakingTargets, stakingIncentives, totalAmounts[0], + totalAmounts[1], totalAmounts[2]); _locked = 1; } diff --git a/contracts/Tokenomics.sol b/contracts/Tokenomics.sol index ea4704ba..98581e8c 100644 --- a/contracts/Tokenomics.sol +++ b/contracts/Tokenomics.sol @@ -247,11 +247,16 @@ struct StakingPoint { uint8 stakingFraction; } -// Struct for service staking epoch info +// Struct for donation point struct DonationPoint { + // Amount of OLAS intended to fund component / agent top-ups for the epoch based on the inflation schedule + // After 10 years, the OLAS inflation rate is 2% per year. It would take 220+ years to reach 2^96 - 1 uint96 totalUnitTopUps; + // Amount of veOLAS power used to trigger top-ups accumulated from all the unique donators per a single epoch + // veOLAS amount cannot practically be bigger than the OLAS amount uint96 totalDonationPower; - bool moreDonationPower; + // Sum of component / agent top-up fractions in a corresponding epoch + uint8 sumTopUpUnitFractions; } /// @title Tokenomics - Smart contract for tokenomics logic with incentives for unit owners, discount factor @@ -381,9 +386,9 @@ contract Tokenomics is TokenomicsConstants { // Mapping of epoch => service staking point mapping(uint256 => StakingPoint) public mapEpochStakingPoints; // Mapping of hash(epoch + donator address) => true the voting power has been utilized in the on-going epoch - mapping(bytes32 => bool) public mapEpochDonatorPowerHashes; + mapping(bytes32 => bool) public mapEpochDonationPowerHashes; // Mapping of epoch => donation point - mapping(uint256 => DonationPoint) mapDonationPoints; + mapping(uint256 => DonationPoint) public mapDonationPoints; /// @dev Tokenomics constructor. constructor() @@ -864,19 +869,20 @@ contract Tokenomics is TokenomicsConstants { // The pendingRelativeTopUp can be zero if the service owner did not stake enough veOLAS // The topUpUnitFraction was checked before and if it were zero, pendingRelativeTopUp would be zero as well if (totalIncentives > 0) { + DonationPoint memory donationPoint = mapDonationPoints[epochNum]; // Summation of all the unit top-ups and total amount of top-ups per epoch - // TODO: update the formula - // topUp = (pendingRelativeTopUp * totalTopUpsOLAS * topUpUnitFraction) / (100 * sumUnitTopUpsOLAS) - if (mapDonationPoints[epochNum].moreDonationPower) { - // TODO: calculate top-ups for components and agents before this function call, before the loop if possible - uint256 totalTopUpsOLAS = mapEpochTokenomics[epochNum].epochPoint.totalTopUpsOLAS; - // TODO: pass this as a function parameter in order to optimize on gas - uint256 totalDonationPower = mapDonationPoints[epochNum].totalDonationPower; - totalIncentives *= totalTopUpsOLAS * mapEpochTokenomics[epochNum].unitPoints[unitType].topUpUnitFraction; - totalIncentives = mapUnitIncentives[unitType][unitId].topUp + (totalIncentives / (totalDonationPower * 100)); + // topUp = (pendingRelativeTopUp * totalUnitTopUps * topUpUnitFraction) / sumTopUpUnitFractions, if totalDonationPower > totalUnitTopUps + // topUp = pendingRelativeTopUp * topUpUnitFraction, otherwise + totalIncentives *= mapEpochTokenomics[epochNum].unitPoints[unitType].topUpUnitFraction; + if (donationPoint.totalDonationPower > donationPoint.totalUnitTopUps) { + totalIncentives = mapUnitIncentives[unitType][unitId].topUp + + (totalIncentives * donationPoint.totalUnitTopUps) / + (donationPoint.totalDonationPower * donationPoint.sumTopUpUnitFractions); } else { - totalIncentives = mapUnitIncentives[unitType][unitId].topUp + totalIncentives; + totalIncentives = mapUnitIncentives[unitType][unitId].topUp + + totalIncentives / donationPoint.sumTopUpUnitFractions; } + // Record the accumulated top-up value mapUnitIncentives[unitType][unitId].topUp = uint96(totalIncentives); // Setting pending top-up to zero mapUnitIncentives[unitType][unitId].pendingRelativeTopUp = 0; @@ -914,9 +920,9 @@ contract Tokenomics is TokenomicsConstants { uint256 vPower; if (incentiveFlags[2] || incentiveFlags[3]) { vPower = IVotingEscrow(ve).getVotes(donator); - bytes32 donatorPowerHash = keccak256(abi.encode(epochCounter, donator)); + bytes32 donationPowerHash = keccak256(abi.encode(epochCounter, donator)); // Check the donator voting power - if (vPower < veOLASThreshold || mapEpochDonatorPowerHashes[donatorPowerHash]) { + if (vPower < veOLASThreshold || mapEpochDonationPowerHashes[donationPowerHash]) { // If voting power is below the threshold or has been already utilized during the on-going epoch, // top-ups are not eligible vPower = 0; @@ -926,7 +932,7 @@ contract Tokenomics is TokenomicsConstants { // Otherwise, split them to the corresponding number of services vPower /= numServices; // Add donator voting power to the map - mapEpochDonatorPowerHashes[donatorPowerHash] = true; + mapEpochDonationPowerHashes[donationPowerHash] = true; } } @@ -1206,11 +1212,11 @@ contract Tokenomics is TokenomicsConstants { // we still record the amount of OLAS allocated for component / agent owner top-ups from the inflation schedule. // This amount will appear in the EpochSettled event, and thus can be tracked historically uint256 accountTopUps = incentives[5] + incentives[6]; - // Record donation power state in a settled epoch - if (mapDonationPoints[eCounter].totalDonationPower > accountTopUps) { - mapDonationPoints[eCounter].moreDonationPower = true; - } - mapDonationPoints[eCounter].totalDonationPower = uint96(accountTopUps); + + // Record total unit top-ups and fractions in a settled epoch + mapDonationPoints[eCounter].totalUnitTopUps = uint96(accountTopUps); + mapDonationPoints[eCounter].sumTopUpUnitFractions = tp.unitPoints[0].topUpUnitFraction + + tp.unitPoints[1].topUpUnitFraction; // Service staking funding // Refunded amount during the epoch @@ -1413,19 +1419,16 @@ contract Tokenomics is TokenomicsConstants { // Add the final top-up for the last epoch totalIncentives = mapUnitIncentives[unitTypes[i]][unitIds[i]].pendingRelativeTopUp; if (totalIncentives > 0) { + DonationPoint memory donationPoint = mapDonationPoints[lastEpoch]; // Summation of all the unit top-ups and total amount of top-ups per epoch - // TODO: update the formula - // topUp = (pendingRelativeTopUp * totalTopUpsOLAS * topUpUnitFraction) / (100 * sumUnitTopUpsOLAS) - // Accumulate to the final top-up for the last epoch - if (mapDonationPoints[lastEpoch].moreDonationPower) { - // TODO: calculate top-ups for components and agents before this function call, before the loop if possible - uint256 totalTopUpsOLAS = mapEpochTokenomics[lastEpoch].epochPoint.totalTopUpsOLAS; - // TODO: pass this as a function parameter in order to optimize on gas - uint256 totalDonationPower = mapDonationPoints[lastEpoch].totalDonationPower; - totalIncentives *= totalTopUpsOLAS * mapEpochTokenomics[lastEpoch].unitPoints[unitTypes[i]].topUpUnitFraction; - totalIncentives = mapUnitIncentives[unitTypes[i]][unitIds[i]].topUp + (totalIncentives / (totalDonationPower * 100)); + // topUp = (pendingRelativeTopUp * totalUnitTopUps * topUpUnitFraction) / sumTopUpUnitFractions, if totalDonationPower > totalUnitTopUps + // topUp = pendingRelativeTopUp * topUpUnitFraction, otherwise + totalIncentives *= mapEpochTokenomics[lastEpoch].unitPoints[unitTypes[i]].topUpUnitFraction; + if (donationPoint.totalDonationPower > donationPoint.totalUnitTopUps) { + topUp += (totalIncentives * donationPoint.totalUnitTopUps) / + (donationPoint.totalDonationPower * donationPoint.sumTopUpUnitFractions); } else { - topUp += totalIncentives; + topUp += totalIncentives / donationPoint.sumTopUpUnitFractions; } } } diff --git a/contracts/test/ReentrancyAttacker.sol b/contracts/test/ReentrancyAttacker.sol index 938f5f13..ebadb4a4 100644 --- a/contracts/test/ReentrancyAttacker.sol +++ b/contracts/test/ReentrancyAttacker.sol @@ -58,6 +58,10 @@ contract ReentrancyAttacker { attackMode = _attackMode; } + /// @dev Makes a deposit from an attacker in order to get top-ups from the inflation + function depositServiceDonationsETH(uint256[] memory serviceIds, uint256[] memory amounts) external payable { + ITokenomics(treasury).depositServiceDonationsETH{value: msg.value}(serviceIds, amounts); + } /// @dev Lets the attacker call back its contract to get back to the claimOwnerIncentives() function. function badClaimOwnerIncentives(bool attack, uint256[] memory unitTypes, uint256[] memory unitIds) external diff --git a/docs/configuration.json b/docs/configuration.json index d6afd484..eca1c39c 100644 --- a/docs/configuration.json +++ b/docs/configuration.json @@ -10,8 +10,8 @@ }, { "name": "Tokenomics", - "artifact": "abis/0.8.20/Tokenomics.json", - "address": "0xD599ED4a5c45Fa66AA3C474b00701Fd452a2C30e" + "artifact": "abis/0.8.25/Tokenomics.json", + "address": "0x2C1633765c66a7CF0EC801a1046347bBee7344C9" }, { "name": "TokenomicsProxy", @@ -30,54 +30,180 @@ }, { "name": "Dispenser", - "artifact": "abis/0.8.18/Dispenser.json", - "address": "0xeED0000fE94d7cfeF4Dc0CA86a223f0F603A61B8" + "artifact": "abis/0.8.25/Dispenser.json", + "address": "0x5650300fCBab43A0D7D02F8Cb5d0f039402593f0" }, { "name": "Depository", "artifact": "abis/0.8.20/Depository.json", "address": "0xfF8697d8d2998d6AA2e09B405795C6F4BEeB0C81" - } - ] - }, - { - "name": "goerli", - "chainId": "5", - "contracts": [ + }, { - "name": "DonatorBlacklist", - "artifact": "abis/0.8.18/DonatorBlacklist.json", - "address": "0x1E11f1224e32Fe0f65FF7D13aD4b053B83bD09FA" + "name": "ArbitrumDepositProcessorL1", + "artifact": "abis/0.8.25/ArbitrumDepositProcessorL1.json", + "address": "0x5e13E07006D68B097DCb5979ef5545C4f9156162" }, { - "name": "Tokenomics", - "artifact": "abis/0.8.20/Tokenomics.json", - "address": "0x93Cd3f6DcE64d67f4420939865A00aC89776D4b5" + "name": "OptimismDepositProcessorL1", + "artifact": "abis/0.8.25/OptimismDepositProcessorL1.json", + "address": "0x42BA1BbD797E4C90F386F03a544F3b62C1f917d0" }, { - "name": "TokenomicsProxy", - "artifact": "abis/0.8.18/TokenomicsProxy.json", - "address": "0x10100e74b7F706222F8A7C0be9FC7Ae1717Ad8B2" + "name": "WormholeDepositProcessorL1", + "artifact": "abis/0.8.25/WormholeDepositProcessorL1.json", + "address": "0x223902b6C583f18E8dc84AF4E6a8fa523d088B78" }, { - "name": "Treasury", - "artifact": "abis/0.8.18/Treasury.json", - "address": "0x7bedCA17D29e53C8062d10902a6219F8d1E3B9B5" + "name": "EthereumDepositProcessor", + "artifact": "abis/0.8.25/EthereumDepositProcessor.json", + "address": "0x15CD7fAeE048c7673aB818C9e582630F1a924593" }, { - "name": "GenericBondCalculator", - "artifact": "abis/0.8.18/GenericBondCalculator.json", - "address": "0x77290FF625fc576f465D0256F6a12Ce4480a5b8a" + "name": "GnosisDepositProcessorL1", + "artifact": "abis/0.8.25/GnosisDepositProcessorL1.json", + "address": "0xEEf2c02cFC445bFFf1c891D486424Ef3aBc66AB0" }, { - "name": "Dispenser", - "artifact": "abis/0.8.18/Dispenser.json", - "address": "0xeDd71796B90eaCc56B074C39BAC90ED2Ca6D93Ee" + "name": "OptimismDepositProcessorL1", + "artifact": "abis/0.8.25/OptimismDepositProcessorL1.json", + "address": "0xAB787ceebe8F2b8dca44e3bB744D6e63003ee978" }, { - "name": "Depository", - "artifact": "abis/0.8.20/Depository.json", - "address": "0x5FDc466f4A7547c876eF40CD30fFA2A89F1EcDE7" + "name": "PolygonDepositProcessorL1", + "artifact": "abis/0.8.25/PolygonDepositProcessorL1.json", + "address": "0x4Ce43b82EF1298E1466D3b3Cee67BA6680bF82FB" + } + ] + }, + { + "name": "arbitrumOne", + "chainId": "42161", + "contracts": [ + { + "name": "ArbitrumTargetDispenserL2", + "artifact": "abis/0.8.25/ArbitrumTargetDispenserL2.json", + "address": "0x10c5525F77F13b28f42c5626240c001c2D57CAd4" + } + ] + }, + { + "name": "arbitrumSepolia", + "chainId": "421614", + "contracts": [ + { + "name": "ArbitrumTargetDispenserL2", + "artifact": "abis/0.8.25/ArbitrumTargetDispenserL2.json", + "address": "" + } + ] + }, + { + "name": "base", + "chainId": "8453", + "contracts": [ + { + "name": "OptimismTargetDispenserL2", + "artifact": "abis/0.8.25/OptimismTargetDispenserL2.json", + "address": "0xcDdD9D9ABaB36fFa882530D69c73FeE5D4001C2d" + } + ] + }, + { + "name": "baseSepolia", + "chainId": "84532", + "contracts": [ + { + "name": "OptimismTargetDispenserL2", + "artifact": "abis/0.8.25/OptimismTargetDispenserL2.json", + "address": "" + } + ] + }, + { + "name": "celo", + "chainId": "42220", + "contracts": [ + { + "name": "WormholeTargetDispenserL2", + "artifact": "abis/0.8.25/WormholeTargetDispenserL2.json", + "address": "0xb4096d181C08DDF75f1A63918cCa0d1023C4e6C7" + } + ] + }, + { + "name": "celoAlfajores", + "chainId": "44787", + "contracts": [ + { + "name": "WormholeTargetDispenserL2", + "artifact": "abis/0.8.25/WormholeTargetDispenserL2.json", + "address": "" + } + ] + }, + { + "name": "gnosis", + "chainId": "100", + "contracts": [ + { + "name": "GnosisTargetDispenserL2", + "artifact": "abis/0.8.25/GnosisTargetDispenserL2.json", + "address": "0x67722c823010CEb4BED5325fE109196C0f67D053" + } + ] + }, + { + "name": "chiado", + "chainId": "10200", + "contracts": [ + { + "name": "GnosisTargetDispenserL2", + "artifact": "abis/0.8.25/GnosisTargetDispenserL2.json", + "address": "" + } + ] + }, + { + "name": "optimistic", + "chainId": "10", + "contracts": [ + { + "name": "OptimismTargetDispenserL2", + "artifact": "abis/0.8.25/OptimismTargetDispenserL2.json", + "address": "0x04b0007b2aFb398015B76e5f22993a1fddF83644" + } + ] + }, + { + "name": "optimisticSepolia", + "chainId": "11155420", + "contracts": [ + { + "name": "OptimismTargetDispenserL2", + "artifact": "abis/0.8.25/OptimismTargetDispenserL2.json", + "address": "" + } + ] + }, + { + "name": "polygon", + "chainId": "137", + "contracts": [ + { + "name": "PolygonTargetDispenserL2", + "artifact": "abis/0.8.25/PolygonTargetDispenserL2.json", + "address": "0xf76953444C35F1FcE2F6CA1b167173357d3F5C17" + } + ] + }, + { + "name": "polygonAmoy", + "chainId": "80002", + "contracts": [ + { + "name": "PolygonTargetDispenserL2", + "artifact": "abis/0.8.25/PolygonTargetDispenserL2.json", + "address": "" } ] } diff --git a/docs/deployment_v1.2.md b/docs/deployment_v1.2.md new file mode 100644 index 00000000..37cbb6ed --- /dev/null +++ b/docs/deployment_v1.2.md @@ -0,0 +1,24 @@ +Steps for deploying the tokenomics version 1.2 contracts are as follows: + +1. EOA to deploy Tokenomics implementation (`TokenomicsThree`); +2. TokenomicsProxy to change Tokenomics implementation calling `changeTokenomicsImplementation(TokenomicsThree)`; +3. EOA to deploy Dispenser with VoteWeighting contract being deployed before that in `autonolas-governance`; +4. EOA to change Dispenser address in VoteWeighting calling `changeDispenser(Dispenser)`; +5. EOA to unpause staking incentives in Dispenser calling `setPauseState(0)`; +6. EOA to add a retainer address as a nominee in VoteWeighting; +7. EOA to deploy staking bridging contracts on L1 and L2 with StakingFactory contract being deployed before that in `autonolas-registries`; +8. EOA to set up correct L1->L2 links for all the bridging contracts calling `setL2TargetDispenser(L2 corresponding contract)`; +9. EOA to enable bridge deposit processors in Dispenser calling `setDepositProcessorChainIds()`; +10. EOA to transfer ownership rights of all the L2 bridging contracts to Timelock representation calling `changeOwner(Timelock)`; +11. EOA to transfer ownership rights of Dispenser to Timelock calling `changeOwner(Timelock)`; +12. DAO to change Tokenomics managers calling `changeManagers(ZeroAddress, ZeroAddress, Dispenser)`; +13. DAO to change staking parameters in Tokenomics calling `changeStakingParams()`; +14. DAO to change Treasury managers calling `changeManagers(ZeroAddress, ZeroAddress, Dispenser)`. + +Note for updating VoteWeighting contract address in Dispenser, if required at some point of time. +As outlined in the C4R [issue 59](https://github.com/code-423n4/2024-05-olas-findings/issues/59), the following set of +steps must be taken into account in order to avoid possible staking inflation loss: +- Initiate claim of incentives for all the outstanding staking contract, as those are ownerless; +- Pause staking incentives; +- Change VoteWeighting contract; +- Unpause staking incentives. \ No newline at end of file diff --git a/scripts/audit_chains/audit_contracts_setup.js b/scripts/audit_chains/audit_contracts_setup.js index 4fd2dc98..f4272176 100644 --- a/scripts/audit_chains/audit_contracts_setup.js +++ b/scripts/audit_chains/audit_contracts_setup.js @@ -3,6 +3,7 @@ const { ethers } = require("ethers"); const { expect } = require("chai"); const fs = require("fs"); +const AddressZero = ethers.constants.AddressZero; // Custom expect that is wrapped into try / catch block function customExpect(arg1, arg2, log) { @@ -58,10 +59,18 @@ async function checkBytecode(provider, configContracts, contractName, log) { } // Find the contract name from the configuration data -async function findContractInstance(provider, configContracts, contractName) { +// idx is to choose the contract, if there are more than one +async function findContractInstance(provider, configContracts, contractName, idx = 0) { + let numFound = 0; // Get the contract number from the set of configuration contracts for (let i = 0; i < configContracts.length; i++) { if (configContracts[i]["name"] === contractName) { + // Keep searching if needed idx is not found + if (numFound != idx) { + numFound++; + continue; + } + // Get the contract instance let contractFromJSON = fs.readFileSync(configContracts[i]["artifact"], "utf8"); @@ -127,7 +136,7 @@ async function checkTokenomicsProxy(chainId, provider, globalsInstance, configCo const implementationHash = await tokenomics.PROXY_TOKENOMICS(); const implementation = await provider.getStorageAt(tokenomics.address, implementationHash); // Need to extract address size of bytes from the storage return value - customExpect("0x" + implementation.slice(-40), globalsInstance["tokenomicsTwoAddress"].toLowerCase(), + customExpect("0x" + implementation.slice(-40), globalsInstance["tokenomicsThreeAddress"].toLowerCase(), log + ", function: PROXY_TOKENOMICS()"); } @@ -166,7 +175,7 @@ async function checkTreasury(chainId, provider, globalsInstance, configContracts // Check paused const paused = await treasury.paused(); - customExpect(paused, false, log + ", function: paused()"); + customExpect(paused, 1, log + ", function: paused()"); } // Check Generic Bond Calculator: chain Id, provider, parsed globals, configuration contracts, contract name @@ -247,10 +256,400 @@ async function checkDepository(chainId, provider, globalsInstance, configContrac customExpect(minVesting, 3600 * 24, log + ", function: VERSION()"); } +// Check DepositProcessorL1: contract, globalsInstance +async function checkDepositProcessorL1(depositProcessorL1, globalsInstance, log) { + log += ", address: " + depositProcessorL1.address; + // Check contract owner + const owner = await depositProcessorL1.owner(); + customExpect(owner, AddressZero, log + ", function: owner()"); + + // Check L1 OLAS token + const olas = await depositProcessorL1.olas(); + customExpect(olas, globalsInstance["olasAddress"], log + ", function: olas()"); + + // Check L1 dispenser + const dispenser = await depositProcessorL1.l1Dispenser(); + customExpect(dispenser, globalsInstance["dispenserAddress"], log + ", function: dispenser ()"); +} + +// Check ArbitrumDepositProcessorL1: chain Id, provider, parsed globals, configuration contracts, contract name +async function checkArbitrumDepositProcessorL1(chainId, provider, globalsInstance, configContracts, contractName, log) { + // Check the bytecode + await checkBytecode(provider, configContracts, contractName, log); + + // Get the contract instance + const arbitrumDepositProcessorL1 = await findContractInstance(provider, configContracts, contractName); + + log += ", address: " + arbitrumDepositProcessorL1.address; + await checkDepositProcessorL1(arbitrumDepositProcessorL1, globalsInstance, log); + + // Check L1 token relayer + const l1TokenRelayer = await arbitrumDepositProcessorL1.l1TokenRelayer(); + customExpect(l1TokenRelayer, globalsInstance["arbitrumL1ERC20GatewayRouterAddress"], log + ", function: l1TokenRelayer()"); + + // Check L1 message relayer + const l1MessageRelayer = await arbitrumDepositProcessorL1.l1MessageRelayer(); + customExpect(l1MessageRelayer, globalsInstance["arbitrumInboxAddress"], log + ", function: l1MessageRelayer()"); + + // Check L2 target chain Id + const l2TargetChainId = await arbitrumDepositProcessorL1.l2TargetChainId(); + customExpect(l2TargetChainId.toString(), globalsInstance["arbitrumL2TargetChainId"], log + ", function: l2TargetChainId()"); + + // Check L1 ERC20Gateway + const l1ERC20Gateway = await arbitrumDepositProcessorL1.l1ERC20Gateway(); + customExpect(l1ERC20Gateway, globalsInstance["arbitrumL1ERC20GatewayAddress"], log + ", function: l1ERC20Gateway()"); + + // Check L1 outbox + const outbox = await arbitrumDepositProcessorL1.outbox(); + customExpect(outbox, globalsInstance["arbitrumOutboxAddress"], log + ", function: outbox()"); + + // Check L1 bridge + const bridge = await arbitrumDepositProcessorL1.bridge(); + customExpect(bridge, globalsInstance["arbitrumBridgeAddress"], log + ", function: bridge()"); + + // Check L2 target dispenser + const l2TargetDispenser = await arbitrumDepositProcessorL1.l2TargetDispenser(); + customExpect(l2TargetDispenser, globalsInstance["arbitrumTargetDispenserL2Address"], log + ", function: l2TargetDispenser()"); +} + +// Check checkEthereumDepositProcessor: chain Id, provider, parsed globals, configuration contracts, contract name +async function checkEthereumDepositProcessor(chainId, provider, globalsInstance, configContracts, contractName, log) { + // Check the bytecode + await checkBytecode(provider, configContracts, contractName, log); + + // Get the contract instance + const ethereumDepositProcessorL1 = await findContractInstance(provider, configContracts, contractName); + + log += ", address: " + ethereumDepositProcessorL1.address; + // Check OLAS token + const olas = await ethereumDepositProcessorL1.olas(); + customExpect(olas, globalsInstance["olasAddress"], log + ", function: olas()"); + + // Check dispenser + const dispenser = await ethereumDepositProcessorL1.dispenser(); + customExpect(dispenser, globalsInstance["dispenserAddress"], log + ", function: dispenser()"); + + // Check L1 staking factory + const stakingFactory = await ethereumDepositProcessorL1.stakingFactory(); + customExpect(stakingFactory, globalsInstance["serviceStakingFactoryAddress"], log + ", function: stakingFactory()"); + + // Check L1 timelock + const timelock = await ethereumDepositProcessorL1.timelock(); + customExpect(timelock, globalsInstance["timelockAddress"], log + ", function: timelock()"); +} + +// Check GnosisDepositProcessorL1: chain Id, provider, parsed globals, configuration contracts, contract name +async function checkGnosisDepositProcessorL1(chainId, provider, globalsInstance, configContracts, contractName, log) { + // Check the bytecode + await checkBytecode(provider, configContracts, contractName, log); + + // Get the contract instance + const gnosisDepositProcessorL1 = await findContractInstance(provider, configContracts, contractName); + + log += ", address: " + gnosisDepositProcessorL1.address; + await checkDepositProcessorL1(gnosisDepositProcessorL1, globalsInstance, log); + + // Check L1 token relayer + const l1TokenRelayer = await gnosisDepositProcessorL1.l1TokenRelayer(); + customExpect(l1TokenRelayer, globalsInstance["gnosisOmniBridgeAddress"], log + ", function: l1TokenRelayer()"); + + // Check L1 message relayer + const l1MessageRelayer = await gnosisDepositProcessorL1.l1MessageRelayer(); + customExpect(l1MessageRelayer, globalsInstance["gnosisAMBForeignAddress"], log + ", function: l1MessageRelayer()"); + + // Check L2 target chain Id + const l2TargetChainId = await gnosisDepositProcessorL1.l2TargetChainId(); + customExpect(l2TargetChainId.toString(), globalsInstance["gnosisL2TargetChainId"], log + ", function: l2TargetChainId()"); + + // Check L2 target dispenser + const l2TargetDispenser = await gnosisDepositProcessorL1.l2TargetDispenser(); + customExpect(l2TargetDispenser, globalsInstance["gnosisTargetDispenserL2Address"], log + ", function: l2TargetDispenser()"); +} + +// Check OptimismDepositProcessorL1: chain Id, provider, parsed globals, configuration contracts, contract name +async function checkOptimismDepositProcessorL1(chainId, provider, globalsInstance, configContracts, contractName, log) { + // Check the bytecode + await checkBytecode(provider, configContracts, contractName, log); + + // Get the contract instance + const optimismDepositProcessorL1 = await findContractInstance(provider, configContracts, contractName, 1); + + log += ", address: " + optimismDepositProcessorL1.address; + await checkDepositProcessorL1(optimismDepositProcessorL1, globalsInstance, log); + + // Check L1 token relayer + const l1TokenRelayer = await optimismDepositProcessorL1.l1TokenRelayer(); + customExpect(l1TokenRelayer, globalsInstance["optimisticL1StandardBridgeProxyAddress"], log + ", function: l1TokenRelayer()"); + + // Check L1 message relayer + const l1MessageRelayer = await optimismDepositProcessorL1.l1MessageRelayer(); + customExpect(l1MessageRelayer, globalsInstance["optimisticL1CrossDomainMessengerProxyAddress"], log + ", function: l1MessageRelayer()"); + + // Check L2 target chain Id + const l2TargetChainId = await optimismDepositProcessorL1.l2TargetChainId(); + customExpect(l2TargetChainId.toString(), globalsInstance["optimisticL2TargetChainId"], log + ", function: l2TargetChainId()"); + + // Check L2 OLAS address + const olasL2 = await optimismDepositProcessorL1.olasL2(); + customExpect(olasL2, globalsInstance["optimisticOLASAddress"], log + ", function: olasL2()"); + + // Check L2 target dispenser + const l2TargetDispenser = await optimismDepositProcessorL1.l2TargetDispenser(); + customExpect(l2TargetDispenser, globalsInstance["optimismTargetDispenserL2Address"], log + ", function: l2TargetDispenser()"); +} + +// Check BaseDepositProcessorL1: chain Id, provider, parsed globals, configuration contracts, contract name +async function checkBaseDepositProcessorL1(chainId, provider, globalsInstance, configContracts, contractName, log) { + // Check the bytecode + await checkBytecode(provider, configContracts, contractName, log); + + // Get the contract instance + const baseDepositProcessorL1 = await findContractInstance(provider, configContracts, contractName); + + log += ", address: " + baseDepositProcessorL1.address; + await checkDepositProcessorL1(baseDepositProcessorL1, globalsInstance, log); + + // Check L1 token relayer + const l1TokenRelayer = await baseDepositProcessorL1.l1TokenRelayer(); + customExpect(l1TokenRelayer, globalsInstance["baseL1StandardBridgeProxyAddress"], log + ", function: l1TokenRelayer()"); + + // Check L1 message relayer + const l1MessageRelayer = await baseDepositProcessorL1.l1MessageRelayer(); + customExpect(l1MessageRelayer, globalsInstance["baseL1CrossDomainMessengerProxyAddress"], log + ", function: l1MessageRelayer()"); + + // Check L2 target chain Id + const l2TargetChainId = await baseDepositProcessorL1.l2TargetChainId(); + customExpect(l2TargetChainId.toString(), globalsInstance["baseL2TargetChainId"], log + ", function: l2TargetChainId()"); + + // Check L2 OLAS address + const olasL2 = await baseDepositProcessorL1.olasL2(); + customExpect(olasL2, globalsInstance["baseOLASAddress"], log + ", function: olasL2()"); + + // Check L2 target dispenser + const l2TargetDispenser = await baseDepositProcessorL1.l2TargetDispenser(); + customExpect(l2TargetDispenser, globalsInstance["baseTargetDispenserL2Address"], log + ", function: l2TargetDispenser()"); +} + +// Check PolygonDepositProcessorL1: chain Id, provider, parsed globals, configuration contracts, contract name +async function checkPolygonDepositProcessorL1(chainId, provider, globalsInstance, configContracts, contractName, log) { + // Check the bytecode + await checkBytecode(provider, configContracts, contractName, log); + + // Get the contract instance + const polygonDepositProcessorL1 = await findContractInstance(provider, configContracts, contractName); + + log += ", address: " + polygonDepositProcessorL1.address; + await checkDepositProcessorL1(polygonDepositProcessorL1, globalsInstance, log); + + // Check L1 token relayer + const l1TokenRelayer = await polygonDepositProcessorL1.l1TokenRelayer(); + customExpect(l1TokenRelayer, globalsInstance["polygonRootChainManagerProxyAddress"], log + ", function: l1TokenRelayer()"); + + // Check L1 message relayer + const l1MessageRelayer = await polygonDepositProcessorL1.l1MessageRelayer(); + customExpect(l1MessageRelayer, globalsInstance["polygonFXRootAddress"], log + ", function: l1MessageRelayer()"); + + // Check L2 target chain Id + const l2TargetChainId = await polygonDepositProcessorL1.l2TargetChainId(); + customExpect(l2TargetChainId.toString(), globalsInstance["polygonL2TargetChainId"], log + ", function: l2TargetChainId()"); + + // Check L1 checkpoint manager + const checkpointManager = await polygonDepositProcessorL1.checkpointManager(); + customExpect(checkpointManager, globalsInstance["polygonCheckpointManagerAddress"], log + ", function: checkpointManager()"); + + // Check L1 predicate + const predicate = await polygonDepositProcessorL1.predicate(); + customExpect(predicate, globalsInstance["polygonERC20PredicateAddress"], log + ", function: predicate()"); + + // Check L2 target dispenser + const l2TargetDispenser = await polygonDepositProcessorL1.l2TargetDispenser(); + customExpect(l2TargetDispenser, globalsInstance["polygonTargetDispenserL2Address"], log + ", function: l2TargetDispenser()"); +} + +// Check CeloDepositProcessorL1: chain Id, provider, parsed globals, configuration contracts, contract name +async function checkCeloDepositProcessorL1(chainId, provider, globalsInstance, configContracts, contractName, log) { + // Check the bytecode + await checkBytecode(provider, configContracts, contractName, log); + + // Get the contract instance + const celoDepositProcessorL1 = await findContractInstance(provider, configContracts, contractName); + + log += ", address: " + celoDepositProcessorL1.address; + await checkDepositProcessorL1(celoDepositProcessorL1, globalsInstance, log); + + // Check L1 token relayer + const l1TokenRelayer = await celoDepositProcessorL1.l1TokenRelayer(); + customExpect(l1TokenRelayer, globalsInstance["wormholeL1TokenRelayerAddress"], log + ", function: l1TokenRelayer()"); + + // Check L1 message relayer + const l1MessageRelayer = await celoDepositProcessorL1.l1MessageRelayer(); + customExpect(l1MessageRelayer, globalsInstance["wormholeL1MessageRelayerAddress"], log + ", function: l1MessageRelayer()"); + + // Check L2 target chain Id + const l2TargetChainId = await celoDepositProcessorL1.l2TargetChainId(); + customExpect(l2TargetChainId.toString(), globalsInstance["celoL2TargetChainId"], log + ", function: l2TargetChainId()"); + + // Check L1 wormhole core + const wormhole = await celoDepositProcessorL1.wormhole(); + customExpect(wormhole, globalsInstance["wormholeL1CoreAddress"], log + ", function: wormhole()"); + + // Check L2 wormhole chain Id format + const wormholeTargetChainId = await celoDepositProcessorL1.wormholeTargetChainId(); + customExpect(wormholeTargetChainId.toString(), globalsInstance["celoWormholeL2TargetChainId"], log + ", function: wormholeTargetChainId()"); + + // Check L2 target dispenser + const l2TargetDispenser = await celoDepositProcessorL1.l2TargetDispenser(); + customExpect(l2TargetDispenser, globalsInstance["celoTargetDispenserL2Address"], log + ", function: l2TargetDispenser()"); +} + +// Check TargetDispenserL2: contract, globalsInstance +async function checkTargetDispenserL2(targetDispenserL2, globalsInstance, log) { + log += ", address: " + targetDispenserL2.address; + // Check contract owner + const owner = await targetDispenserL2.owner(); + customExpect(owner, globalsInstance["bridgeMediatorAddress"], log + ", function: owner()"); + + // Check L2 OLAS token + const olas = await targetDispenserL2.olas(); + customExpect(olas, globalsInstance["olasAddress"], log + ", function: olas()"); + + // Check L2 staking factory + const stakingFactory = await targetDispenserL2.stakingFactory(); + customExpect(stakingFactory, globalsInstance["serviceStakingFactoryAddress"], log + ", function: stakingFactory()"); + + // Check L1 source chain Id + const l1SourceChainId = await targetDispenserL2.l1SourceChainId(); + customExpect(l1SourceChainId.toString(), globalsInstance["l1ChainId"], log + ", function: l1SourceChainId()"); +} + +// Check PolygonTargetDispenserL2: chain Id, provider, parsed globals, configuration contracts, contract name +async function checkPolygonTargetDispenserL2(chainId, provider, globalsInstance, configContracts, contractName, log) { + // Check the bytecode + await checkBytecode(provider, configContracts, contractName, log); + + // Get the contract instance + const polygonTargetDispenserL2 = await findContractInstance(provider, configContracts, contractName); + + log += ", address: " + polygonTargetDispenserL2.address; + await checkTargetDispenserL2(polygonTargetDispenserL2, globalsInstance, log); + + // Check L2 message relayer + const l2MessageRelayer = await polygonTargetDispenserL2.l2MessageRelayer(); + customExpect(l2MessageRelayer, globalsInstance["polygonFXChildAddress"], log + ", function: l2MessageRelayer()"); + + // Check L1 deposit processor + const l1DepositProcessor = await polygonTargetDispenserL2.l1DepositProcessor(); + customExpect(l1DepositProcessor, globalsInstance["polygonDepositProcessorL1Address"], log + ", function: l1DepositProcessor()"); +} + +// Check GnosisTargetDispenserL2: chain Id, provider, parsed globals, configuration contracts, contract name +async function checkGnosisTargetDispenserL2(chainId, provider, globalsInstance, configContracts, contractName, log) { + // Check the bytecode + await checkBytecode(provider, configContracts, contractName, log); + + // Get the contract instance + const gnosisTargetDispenserL2 = await findContractInstance(provider, configContracts, contractName); + + log += ", address: " + gnosisTargetDispenserL2.address; + await checkTargetDispenserL2(gnosisTargetDispenserL2, globalsInstance, log); + + // Check L2 message relayer + const l2MessageRelayer = await gnosisTargetDispenserL2.l2MessageRelayer(); + customExpect(l2MessageRelayer, globalsInstance["gnosisAMBHomeAddress"], log + ", function: l2MessageRelayer()"); + + // Check L1 deposit processor + const l1DepositProcessor = await gnosisTargetDispenserL2.l1DepositProcessor(); + customExpect(l1DepositProcessor, globalsInstance["gnosisDepositProcessorL1Address"], log + ", function: l1DepositProcessor()"); +} + +// Check ArbitrumTargetDispenserL2: chain Id, provider, parsed globals, configuration contracts, contract name +async function checkArbitrumTargetDispenserL2(chainId, provider, globalsInstance, configContracts, contractName, log) { + // Check the bytecode + await checkBytecode(provider, configContracts, contractName, log); + + // Get the contract instance + const arbitrumTargetDispenserL2 = await findContractInstance(provider, configContracts, contractName); + + log += ", address: " + arbitrumTargetDispenserL2.address; + await checkTargetDispenserL2(arbitrumTargetDispenserL2, globalsInstance, log); + + // Check L2 message relayer + const l2MessageRelayer = await arbitrumTargetDispenserL2.l2MessageRelayer(); + customExpect(l2MessageRelayer, globalsInstance["arbitrumArbSysAddress"], log + ", function: l2MessageRelayer()"); + + // Check L1 deposit processor + const l1DepositProcessor = await arbitrumTargetDispenserL2.l1DepositProcessor(); + customExpect(l1DepositProcessor, globalsInstance["arbitrumDepositProcessorL1Address"], log + ", function: l1DepositProcessor()"); +} + +// Check OptimismTargetDispenserL2: chain Id, provider, parsed globals, configuration contracts, contract name +async function checkOptimismTargetDispenserL2(chainId, provider, globalsInstance, configContracts, contractName, log) { + // Check the bytecode + await checkBytecode(provider, configContracts, contractName, log); + + // Get the contract instance + const optimismTargetDispenserL2 = await findContractInstance(provider, configContracts, contractName); + + log += ", address: " + optimismTargetDispenserL2.address; + await checkTargetDispenserL2(optimismTargetDispenserL2, globalsInstance, log); + + // Check L2 message relayer + const l2MessageRelayer = await optimismTargetDispenserL2.l2MessageRelayer(); + customExpect(l2MessageRelayer, globalsInstance["optimisticL2CrossDomainMessengerAddress"], log + ", function: l2MessageRelayer()"); + + // Check L1 deposit processor + const l1DepositProcessor = await optimismTargetDispenserL2.l1DepositProcessor(); + customExpect(l1DepositProcessor, globalsInstance["optimismDepositProcessorL1Address"], log + ", function: l1DepositProcessor()"); +} + +// Check BaseTargetDispenserL2: chain Id, provider, parsed globals, configuration contracts, contract name +async function checkBaseTargetDispenserL2(chainId, provider, globalsInstance, configContracts, contractName, log) { + // Check the bytecode + await checkBytecode(provider, configContracts, contractName, log); + + // Get the contract instance + const baseTargetDispenserL2 = await findContractInstance(provider, configContracts, contractName); + + log += ", address: " + baseTargetDispenserL2.address; + await checkTargetDispenserL2(baseTargetDispenserL2, globalsInstance, log); + + // Check L2 message relayer + const l2MessageRelayer = await baseTargetDispenserL2.l2MessageRelayer(); + customExpect(l2MessageRelayer, globalsInstance["baseL2CrossDomainMessengerAddress"], log + ", function: l2MessageRelayer()"); + + // Check L1 deposit processor + const l1DepositProcessor = await baseTargetDispenserL2.l1DepositProcessor(); + customExpect(l1DepositProcessor, globalsInstance["baseDepositProcessorL1Address"], log + ", function: l1DepositProcessor()"); +} + +// Check CeloTargetDispenserL2: chain Id, provider, parsed globals, configuration contracts, contract name +async function checkCeloTargetDispenserL2(chainId, provider, globalsInstance, configContracts, contractName, log) { + // Check the bytecode + await checkBytecode(provider, configContracts, contractName, log); + + // Get the contract instance + const celoTargetDispenserL2 = await findContractInstance(provider, configContracts, contractName); + + log += ", address: " + celoTargetDispenserL2.address; + await checkTargetDispenserL2(celoTargetDispenserL2, globalsInstance, log); + + // Check L2 message relayer + const l2MessageRelayer = await celoTargetDispenserL2.l2MessageRelayer(); + customExpect(l2MessageRelayer, globalsInstance["wormholeL2MessageRelayer"], log + ", function: l2MessageRelayer()"); + + // Check L1 deposit processor + const l1DepositProcessor = await celoTargetDispenserL2.l1DepositProcessor(); + customExpect(l1DepositProcessor, globalsInstance["celoDepositProcessorL1Address"], log + ", function: l1DepositProcessor()"); + + // Check L2 wormhole core + const wormhole = await celoTargetDispenserL2.wormhole(); + customExpect(wormhole, globalsInstance["wormholeL2CoreAddress"], log + ", function: wormhole()"); +} + async function main() { // Check for the API keys - if (!process.env.ALCHEMY_API_KEY_MAINNET || !process.env.ALCHEMY_API_KEY_GOERLI || - !process.env.ALCHEMY_API_KEY_MATIC || !process.env.ALCHEMY_API_KEY_MUMBAI) { + if (!process.env.ALCHEMY_API_KEY_MAINNET || !process.env.ALCHEMY_API_KEY_SEPOLIA || + !process.env.ALCHEMY_API_KEY_MATIC || !process.env.ALCHEMY_API_KEY_AMOY) { console.log("Check API keys!"); return; } @@ -260,87 +659,144 @@ async function main() { const dataFromJSON = fs.readFileSync(configFile, "utf8"); const configs = JSON.parse(dataFromJSON); - const numChains = configs.length; // ################################# VERIFY CONTRACTS WITH REPO ################################# - // For now gnosis chains are not supported - const networks = { - "mainnet": "etherscan", - "goerli": "goerli.etherscan", - }; - console.log("\nVerifying deployed contracts vs the repo... If no error is output, then the contracts are correct."); - // Traverse all chains - for (let i = 0; i < numChains; i++) { - // Skip gnosis chains - if (!networks[configs[i]["name"]]) { + // Currently the verification is fo mainnet only + const network = "etherscan"; + const contracts = configs[0]["contracts"]; + + // Verify contracts + for (let i = 0; i < contracts.length; i++) { + console.log("Checking " + contracts[i]["name"]); + const execSync = require("child_process").execSync; + try { + execSync("scripts/audit_chains/audit_repo_contract.sh " + network + " " + contracts[i]["name"] + " " + contracts[i]["address"]); + } catch (error) { continue; } - - console.log("\n\nNetwork:", configs[i]["name"]); - const network = networks[configs[i]["name"]]; - const contracts = configs[i]["contracts"]; - - // Verify contracts - for (let j = 0; j < contracts.length; j++) { - console.log("Checking " + contracts[j]["name"]); - const execSync = require("child_process").execSync; - try { - execSync("scripts/audit_chains/audit_repo_contract.sh " + network + " " + contracts[j]["name"] + " " + contracts[j]["address"]); - } catch (error) { - continue; - } - } } // ################################# /VERIFY CONTRACTS WITH REPO ################################# // ################################# VERIFY CONTRACTS SETUP ################################# const globalNames = { "mainnet": "scripts/deployment/globals_mainnet.json", - "goerli": "scripts/deployment/globals_goerli.json", + "polygon": "scripts/deployment/staking/polygon/globals_polygon_mainnet.json", + "gnosis": "scripts/deployment/staking/gnosis/globals_gnosis_mainnet.json", + "arbitrumOne": "scripts/deployment/staking/arbitrum/globals_arbitrum_one.json", + "optimistic": "scripts/deployment/staking/optimistic/globals_optimistic_mainnet.json", + "base": "scripts/deployment/staking/base/globals_base_mainnet.json", + "celo": "scripts/deployment/staking/celo/globals_celo_mainnet.json" }; + const globals = new Array(); + for (let k in globalNames) { + const dataJSON = fs.readFileSync(globalNames[k], "utf8"); + globals.push(JSON.parse(dataJSON)); + } + // Special case for staking (also on L1) + const dataJSON = fs.readFileSync("scripts/deployment/staking/globals_mainnet.json", "utf8"); + const globalsStaking = JSON.parse(dataJSON); + + const providerLinks = { "mainnet": "https://eth-mainnet.g.alchemy.com/v2/" + process.env.ALCHEMY_API_KEY_MAINNET, - "goerli": "https://eth-goerli.g.alchemy.com/v2/" + process.env.ALCHEMY_API_KEY_GOERLI, + "polygon": "https://polygon-mainnet.g.alchemy.com/v2/" + process.env.ALCHEMY_API_KEY_MATIC, + "gnosis": "https://rpc.gnosischain.com", + "arbitrumOne": "https://arb1.arbitrum.io/rpc", + "optimistic": "https://optimism.drpc.org", + "base": "https://mainnet.base.org", + "celo": "https://forno.celo.org" }; - // Get all the globals processed - const globals = new Array(); const providers = new Array(); - for (let i = 0; i < numChains; i++) { - const dataJSON = fs.readFileSync(globalNames[configs[i]["name"]], "utf8"); - globals.push(JSON.parse(dataJSON)); - const provider = new ethers.providers.JsonRpcProvider(providerLinks[configs[i]["name"]]); + for (let k in providerLinks) { + const provider = new ethers.providers.JsonRpcProvider(providerLinks[k]); providers.push(provider); } console.log("\nVerifying deployed contracts setup... If no error is output, then the contracts are correct."); // L1 contracts - for (let i = 0; i < 2; i++) { - console.log("\n######## Verifying setup on CHAIN ID", configs[i]["chainId"]); + console.log("\n######## Verifying setup on CHAIN ID", configs[0]["chainId"]); - const initLog = "ChainId: " + configs[i]["chainId"] + ", network: " + configs[i]["name"]; + let initLog = "ChainId: " + configs[0]["chainId"] + ", network: " + configs[0]["name"]; - let log = initLog + ", contract: " + "DonatorBlacklist"; - await checkDonatorBlacklist(configs[i]["chainId"], providers[i], globals[i], configs[i]["contracts"], "DonatorBlacklist", log); + let log = initLog + ", contract: " + "DonatorBlacklist"; + await checkDonatorBlacklist(configs[0]["chainId"], providers[0], globals[0], configs[0]["contracts"], "DonatorBlacklist", log); - log = initLog + ", contract: " + "TokenomicsProxy"; - await checkTokenomicsProxy(configs[i]["chainId"], providers[i], globals[i], configs[i]["contracts"], "TokenomicsProxy", log); + log = initLog + ", contract: " + "TokenomicsProxy"; + await checkTokenomicsProxy(configs[0]["chainId"], providers[0], globals[0], configs[0]["contracts"], "TokenomicsProxy", log); - log = initLog + ", contract: " + "Treasury"; - await checkTreasury(configs[i]["chainId"], providers[i], globals[i], configs[i]["contracts"], "Treasury", log); + log = initLog + ", contract: " + "Treasury"; + await checkTreasury(configs[0]["chainId"], providers[0], globals[0], configs[0]["contracts"], "Treasury", log); - log = initLog + ", contract: " + "GenericBondCalculator"; - await checkGenericBondCalculator(configs[i]["chainId"], providers[i], globals[i], configs[i]["contracts"], "GenericBondCalculator", log); + log = initLog + ", contract: " + "GenericBondCalculator"; + await checkGenericBondCalculator(configs[0]["chainId"], providers[0], globals[0], configs[0]["contracts"], "GenericBondCalculator", log); - log = initLog + ", contract: " + "Dispenser"; - await checkDispenser(configs[i]["chainId"], providers[i], globals[i], configs[i]["contracts"], "Dispenser", log); + log = initLog + ", contract: " + "Dispenser"; + await checkDispenser(configs[0]["chainId"], providers[0], globals[0], configs[0]["contracts"], "Dispenser", log); - log = initLog + ", contract: " + "Depository"; - await checkDepository(configs[i]["chainId"], providers[i], globals[i], configs[i]["contracts"], "Depository", log); - } + log = initLog + ", contract: " + "Depository"; + await checkDepository(configs[0]["chainId"], providers[0], globals[0], configs[0]["contracts"], "Depository", log); + + log = initLog + ", contract: " + "ArbitrumDepositProcessorL1"; + await checkArbitrumDepositProcessorL1(configs[0]["chainId"], providers[0], globalsStaking, configs[0]["contracts"], "ArbitrumDepositProcessorL1", log); + + log = initLog + ", contract: " + "EthereumDepositProcessor"; + await checkEthereumDepositProcessor(configs[0]["chainId"], providers[0], globalsStaking, configs[0]["contracts"], "EthereumDepositProcessor", log); + + log = initLog + ", contract: " + "GnosisDepositProcessorL1"; + await checkGnosisDepositProcessorL1(configs[0]["chainId"], providers[0], globalsStaking, configs[0]["contracts"], "GnosisDepositProcessorL1", log); + + log = initLog + ", contract: " + "OptimismDepositProcessorL1"; + await checkOptimismDepositProcessorL1(configs[0]["chainId"], providers[0], globalsStaking, configs[0]["contracts"], "OptimismDepositProcessorL1", log); + + log = initLog + ", contract: " + "BaseDepositProcessorL1"; + await checkBaseDepositProcessorL1(configs[0]["chainId"], providers[0], globalsStaking, configs[0]["contracts"], "OptimismDepositProcessorL1", log); + + log = initLog + ", contract: " + "PolygonDepositProcessorL1"; + await checkPolygonDepositProcessorL1(configs[0]["chainId"], providers[0], globalsStaking, configs[0]["contracts"], "PolygonDepositProcessorL1", log); + + log = initLog + ", contract: " + "CeloDepositProcessorL1"; + await checkCeloDepositProcessorL1(configs[0]["chainId"], providers[0], globalsStaking, configs[0]["contracts"], "WormholeDepositProcessorL1", log); + + // L2 contracts + // Polygon + console.log("\n######## Verifying setup on CHAIN ID", configs[11]["chainId"]); + initLog = "ChainId: " + configs[11]["chainId"] + ", network: " + configs[11]["name"]; + log = initLog + ", contract: " + "PolygonTargetDispenserL2"; + await checkPolygonTargetDispenserL2(configs[11]["chainId"], providers[1], globals[1], configs[11]["contracts"], "PolygonTargetDispenserL2", log); + + // Gnosis + console.log("\n######## Verifying setup on CHAIN ID", configs[7]["chainId"]); + initLog = "ChainId: " + configs[7]["chainId"] + ", network: " + configs[7]["name"]; + log = initLog + ", contract: " + "GnosisTargetDispenserL2"; + await checkGnosisTargetDispenserL2(configs[7]["chainId"], providers[2], globals[2], configs[7]["contracts"], "GnosisTargetDispenserL2", log); + + // Arbitrum + console.log("\n######## Verifying setup on CHAIN ID", configs[1]["chainId"]); + initLog = "ChainId: " + configs[1]["chainId"] + ", network: " + configs[1]["name"]; + log = initLog + ", contract: " + "ArbitrumTargetDispenserL2"; + await checkArbitrumTargetDispenserL2(configs[1]["chainId"], providers[3], globals[3], configs[1]["contracts"], "ArbitrumTargetDispenserL2", log); + + // Base + console.log("\n######## Verifying setup on CHAIN ID", configs[3]["chainId"]); + initLog = "ChainId: " + configs[3]["chainId"] + ", network: " + configs[3]["name"]; + log = initLog + ", contract: " + "BaseTargetDispenserL2"; + await checkBaseTargetDispenserL2(configs[3]["chainId"], providers[5], globals[5], configs[3]["contracts"], "OptimismTargetDispenserL2", log); + + // Celo + console.log("\n######## Verifying setup on CHAIN ID", configs[5]["chainId"]); + initLog = "ChainId: " + configs[5]["chainId"] + ", network: " + configs[5]["name"]; + log = initLog + ", contract: " + "CeloTargetDispenserL2"; + await checkCeloTargetDispenserL2(configs[5]["chainId"], providers[6], globals[6], configs[5]["contracts"], "WormholeTargetDispenserL2", log); + + // Optimism + console.log("\n######## Verifying setup on CHAIN ID", configs[9]["chainId"]); + initLog = "ChainId: " + configs[9]["chainId"] + ", network: " + configs[9]["name"]; + log = initLog + ", contract: " + "OptimismTargetDispenserL2"; + await checkOptimismTargetDispenserL2(configs[9]["chainId"], providers[4], globals[4], configs[9]["contracts"], "OptimismTargetDispenserL2", log); // ################################# /VERIFY CONTRACTS SETUP ################################# } diff --git a/scripts/deployment/README.md b/scripts/deployment/README.md index 1376022f..66b9e2e0 100644 --- a/scripts/deployment/README.md +++ b/scripts/deployment/README.md @@ -1,5 +1,8 @@ # Deployment scripts -This folder contains the scripts to deploy Autonolas tokenomics. These scripts correspond to the steps in the full deployment procedure (as described in [deployment.md](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/docs/deployment.md)). +This folder contains the scripts to deploy Autonolas tokenomics. +These scripts correspond to the steps in the full deployment procedure (as described in [deployment.md](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/docs/deployment.md)). + +For the Tokenomics 1.2, refer to the following deployment procedure: [deployment_v1.2.md](https://github.com/valory-xyz/autonolas-tokenomics/blob/main/docs/deployment_v1.2.md). ## Observations - There are several files with global parameters based on the corresponding network. In order to work with the configuration, please copy `gobals_network.json` file to file the `gobals.json` one, where `network` is the corresponding network. For example: `cp gobals_goerli.json gobals.json`. diff --git a/scripts/deployment/deploy_07_dispenser.js b/scripts/deployment/deploy_07_dispenser.js index f62d53f7..9fb45ef4 100644 --- a/scripts/deployment/deploy_07_dispenser.js +++ b/scripts/deployment/deploy_07_dispenser.js @@ -26,25 +26,35 @@ async function main() { console.log("EOA is:", deployer); // Get all the necessary contract addresses + const olasAddress = parsedData.olasAddress; const tokenomicsProxyAddress = parsedData.tokenomicsProxyAddress; const treasuryAddress = parsedData.treasuryAddress; + const voteWeightingAddress = parsedData.voteWeightingAddress; + const retainerAddress = parsedData.retainerAddress; + const maxNumClaimingEpochs = parsedData.maxNumClaimingEpochs; + const maxNumStakingTargets = parsedData.maxNumStakingTargets; + const minStakingWeight = parsedData.minStakingWeight; + const maxStakingIncentive = parsedData.maxStakingIncentive; // Transaction signing and execution console.log("7. EOA to deploy Dispenser"); const Dispenser = await ethers.getContractFactory("Dispenser"); console.log("You are signing the following transaction: Dispenser.connect(EOA).deploy()"); - const dispenser = await Dispenser.connect(EOA).deploy(tokenomicsProxyAddress, treasuryAddress); + const dispenser = await Dispenser.connect(EOA).deploy(olasAddress, tokenomicsProxyAddress, treasuryAddress, + voteWeightingAddress, retainerAddress, maxNumClaimingEpochs, maxNumStakingTargets, minStakingWeight, + maxStakingIncentive); const result = await dispenser.deployed(); - // If on goerli, wait a minute for the transaction completion - if (providerName === "goerli") { - await new Promise(r => setTimeout(r, 60000)); - } // Transaction details console.log("Contract deployment: Dispenser"); console.log("Contract address:", dispenser.address); console.log("Transaction:", result.deployTransaction.hash); + // If on sepolia, wait half a minute for the transaction completion + if (providerName === "sepolia") { + await new Promise(r => setTimeout(r, 30000)); + } + // Contract verification if (parsedData.contractVerification) { const execSync = require("child_process").execSync; diff --git a/scripts/deployment/globals_mainnet.json b/scripts/deployment/globals_mainnet.json index 3f165c8f..9344fce1 100644 --- a/scripts/deployment/globals_mainnet.json +++ b/scripts/deployment/globals_mainnet.json @@ -1 +1 @@ -{"contractVerification":true,"useLedger":true,"derivationPath":"m/44'/60'/2'/0/0","providerName":"mainnet","olasAddress":"0x0001A500A6B18995B03f44bb040A5fFc28E45CB0","timelockAddress":"0x3C1fF68f5aa342D296d4DEe4Bb1cACCA912D95fE","veOLASAddress":"0x7e01A500805f8A52Fad229b3015AD130A332B7b3","governorAddress":"0x34C895f302D0b5cf52ec0Edd3945321EB0f83dd5","governorTwoAddress":"0x4E3e48bA826b15214FDe72a50BFd17aB286B584E","componentRegistryAddress":"0x15bd56669F57192a97dF41A2aa8f4403e9491776","agentRegistryAddress":"0x2F1f7D38e4772884b88f3eCd8B6b9faCdC319112","serviceRegistryAddress":"0x48b6af7B12C71f09e2fC8aF4855De4Ff54e775cA","epochLen":"2592000","donatorBlacklistAddress":"0xE85791B18F5df42163092Acc5C9da1c479AFEa9d","tokenomicsAddress":"0x87f89F94033305791B6269AE2F9cF4e09983E56e","tokenomicsProxyAddress":"0xc096362fa6f4A4B1a9ea68b1043416f3381ce300","treasuryAddress":"0xa0DA53447C0f6C4987964d8463da7e6628B30f82","genericBondCalculatorAddress":"0x1521918961bDBC9Ed4C67a7103D5999e4130E6CB","depositoryAddress":"0x52A043bcebdB2f939BaEF2E8b6F01652290eAB3f","dispenserAddress":"0xeED0000fE94d7cfeF4Dc0CA86a223f0F603A61B8","tokenomicsTwoAddress":"0xD599ED4a5c45Fa66AA3C474b00701Fd452a2C30e","OLAS_ETH_PairAddress":"0x09D1d767eDF8Fa23A64C51fa559E0688E526812F","depositoryTwoAddress":"0xfF8697d8d2998d6AA2e09B405795C6F4BEeB0C81","XOLAS_WXDAI_PairAddress":"0x27df632fd0dcf191C418c803801D521cd579F18e","tokenomicsThreeAddress":"0x2C1633765c66a7CF0EC801a1046347bBee7344C9"} \ No newline at end of file +{"contractVerification":true,"useLedger":true,"derivationPath":"m/44'/60'/2'/0/0","providerName":"mainnet","olasAddress":"0x0001A500A6B18995B03f44bb040A5fFc28E45CB0","timelockAddress":"0x3C1fF68f5aa342D296d4DEe4Bb1cACCA912D95fE","veOLASAddress":"0x7e01A500805f8A52Fad229b3015AD130A332B7b3","governorAddress":"0x34C895f302D0b5cf52ec0Edd3945321EB0f83dd5","governorTwoAddress":"0x4E3e48bA826b15214FDe72a50BFd17aB286B584E","componentRegistryAddress":"0x15bd56669F57192a97dF41A2aa8f4403e9491776","agentRegistryAddress":"0x2F1f7D38e4772884b88f3eCd8B6b9faCdC319112","serviceRegistryAddress":"0x48b6af7B12C71f09e2fC8aF4855De4Ff54e775cA","epochLen":"2592000","donatorBlacklistAddress":"0xE85791B18F5df42163092Acc5C9da1c479AFEa9d","tokenomicsAddress":"0x87f89F94033305791B6269AE2F9cF4e09983E56e","tokenomicsProxyAddress":"0xc096362fa6f4A4B1a9ea68b1043416f3381ce300","treasuryAddress":"0xa0DA53447C0f6C4987964d8463da7e6628B30f82","genericBondCalculatorAddress":"0x1521918961bDBC9Ed4C67a7103D5999e4130E6CB","depositoryAddress":"0x52A043bcebdB2f939BaEF2E8b6F01652290eAB3f","dispenserAddress":"0x5650300fCBab43A0D7D02F8Cb5d0f039402593f0","tokenomicsTwoAddress":"0xD599ED4a5c45Fa66AA3C474b00701Fd452a2C30e","OLAS_ETH_PairAddress":"0x09D1d767eDF8Fa23A64C51fa559E0688E526812F","depositoryTwoAddress":"0xfF8697d8d2998d6AA2e09B405795C6F4BEeB0C81","XOLAS_WXDAI_PairAddress":"0x27df632fd0dcf191C418c803801D521cd579F18e","tokenomicsThreeAddress":"0x2C1633765c66a7CF0EC801a1046347bBee7344C9","voteWeightingAddress":"0x95418b46d5566d3d1ea62c12aea91227e566c5c1","retainerAddress":"0x000000000000000000000000000000000000000000000000000000000000dEaD","maxNumClaimingEpochs":"1","maxNumStakingTargets":"10","minStakingWeight":"100","maxStakingIncentive":"30000000000000000000000"} \ No newline at end of file diff --git a/scripts/deployment/staking/arbitrum/deploy_21_change_owner.js b/scripts/deployment/staking/arbitrum/deploy_21_change_owner.js new file mode 100644 index 00000000..f05cdf37 --- /dev/null +++ b/scripts/deployment/staking/arbitrum/deploy_21_change_owner.js @@ -0,0 +1,48 @@ +/*global process*/ + +const { ethers } = require("hardhat"); +const { LedgerSigner } = require("@anders-t/ethers-ledger"); + +async function main() { + const fs = require("fs"); + const globalsFile = "globals.json"; + const dataFromJSON = fs.readFileSync(globalsFile, "utf8"); + let parsedData = JSON.parse(dataFromJSON); + const useLedger = parsedData.useLedger; + const derivationPath = parsedData.derivationPath; + const providerName = parsedData.providerName; + const arbitrumTargetDispenserL2Address = parsedData.arbitrumTargetDispenserL2Address; + const bridgeMediatorAddress = parsedData.bridgeMediatorAddress; + + let networkURL = parsedData.networkURL; + const provider = new ethers.providers.JsonRpcProvider(networkURL); + const signers = await ethers.getSigners(); + + let EOA; + if (useLedger) { + EOA = new LedgerSigner(provider, derivationPath); + } else { + EOA = signers[0]; + } + // EOA address + const deployer = await EOA.getAddress(); + console.log("EOA is:", deployer); + + // Transaction signing and execution + console.log("21. EOA to change owner in ArbitrumTargetDispenserL2"); + const arbitrumTargetDispenserL2 = await ethers.getContractAt("ArbitrumTargetDispenserL2", arbitrumTargetDispenserL2Address); + console.log("You are signing the following transaction: ArbitrumTargetDispenserL2.connect(EOA).changeOwner()"); + const result = await arbitrumTargetDispenserL2.connect(EOA).changeOwner(bridgeMediatorAddress); + + // Transaction details + console.log("Contract deployment: ArbitrumTargetDispenserL2"); + console.log("Contract address:", arbitrumTargetDispenserL2.address); + console.log("Transaction:", result.hash); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/scripts/deployment/staking/arbitrum/globals_arbitrum_one.json b/scripts/deployment/staking/arbitrum/globals_arbitrum_one.json new file mode 100644 index 00000000..cc50b481 --- /dev/null +++ b/scripts/deployment/staking/arbitrum/globals_arbitrum_one.json @@ -0,0 +1 @@ +{"contractVerification":true,"useLedger":true,"derivationPath":"m/44'/60'/2'/0/0","providerName":"arbitrumOne","networkURL":"https://arb1.arbitrum.io/rpc","gasPriceInGwei":"5","olasAddress":"0x064F8B858C2A603e1b106a2039f5446D32dc81c1","serviceStakingFactoryAddress":"0xEB5638eefE289691EcE01943f768EDBF96258a80","bridgeMediatorAddress":"0x4d30F68F5AA342d296d4deE4bB1Cacca912dA70F","arbitrumArbSysAddress":"0x0000000000000000000000000000000000000064","l1ChainId":"1","arbitrumDepositProcessorL1Address":"0x5e13E07006D68B097DCb5979ef5545C4f9156162","arbitrumTargetDispenserL2Address":"0x10c5525F77F13b28f42c5626240c001c2D57CAd4"} \ No newline at end of file diff --git a/scripts/deployment/staking/arbitrum/send_tokens_and_message.js b/scripts/deployment/staking/arbitrum/send_tokens_and_message.js index a691b901..482790f2 100644 --- a/scripts/deployment/staking/arbitrum/send_tokens_and_message.js +++ b/scripts/deployment/staking/arbitrum/send_tokens_and_message.js @@ -163,7 +163,7 @@ const main = async () => { await tx.wait(); // tx back to L1: https://sepolia.arbiscan.io/tx/0xea8119b1030bb223a896680d9c4ea03877beee08927ef1b8a9532ce48db68c55 - // Finalized tx on L1: + // Finalized tx on L1: https://sepolia.etherscan.io/tx/0x5f61dd72b5feb31af563f7af76402e523e1e871bdac7f1a82bb0ffefcd333ebb // Use the following script to finalize L2-L1 transaction: // https://github.com/OffchainLabs/arbitrum-tutorials/blob/master/packages/outbox-execute/scripts/exec.js diff --git a/scripts/deployment/staking/base/deploy_07_base_targer_dispenser.js b/scripts/deployment/staking/base/deploy_07_base_targer_dispenser.js new file mode 100644 index 00000000..13bd32fc --- /dev/null +++ b/scripts/deployment/staking/base/deploy_07_base_targer_dispenser.js @@ -0,0 +1,75 @@ +/*global process*/ + +const { ethers } = require("hardhat"); +const { LedgerSigner } = require("@anders-t/ethers-ledger"); + +async function main() { + const fs = require("fs"); + const globalsFile = "globals.json"; + const dataFromJSON = fs.readFileSync(globalsFile, "utf8"); + let parsedData = JSON.parse(dataFromJSON); + const useLedger = parsedData.useLedger; + const derivationPath = parsedData.derivationPath; + const providerName = parsedData.providerName; + + let networkURL = parsedData.networkURL; + if (providerName === "polygon") { + if (!process.env.ALCHEMY_API_KEY_MATIC) { + console.log("set ALCHEMY_API_KEY_MATIC env variable"); + } + networkURL += process.env.ALCHEMY_API_KEY_MATIC; + } else if (providerName === "polygonAmoy") { + if (!process.env.ALCHEMY_API_KEY_AMOY) { + console.log("set ALCHEMY_API_KEY_AMOY env variable"); + return; + } + networkURL += process.env.ALCHEMY_API_KEY_AMOY; + } + + const provider = new ethers.providers.JsonRpcProvider(networkURL); + const signers = await ethers.getSigners(); + + let EOA; + if (useLedger) { + EOA = new LedgerSigner(provider, derivationPath); + } else { + EOA = signers[0]; + } + // EOA address + const deployer = await EOA.getAddress(); + console.log("EOA is:", deployer); + + // Transaction signing and execution + console.log("7. EOA to deploy OptimismTargetDispenserL2 for Base"); + const OptimismTargetDispenserL2 = await ethers.getContractFactory("OptimismTargetDispenserL2"); + console.log("You are signing the following transaction: OptimismTargetDispenserL2.connect(EOA).deploy()"); + const baseTargetDispenserL2 = await OptimismTargetDispenserL2.connect(EOA).deploy(parsedData.olasAddress, + parsedData.serviceStakingFactoryAddress, parsedData.baseL2CrossDomainMessengerAddress, + parsedData.baseDepositProcessorL1Address, parsedData.l1ChainId); + const result = await baseTargetDispenserL2.deployed(); + + // Transaction details + console.log("Contract deployment: OptimismTargetDispenserL2"); + console.log("Contract address:", baseTargetDispenserL2.address); + console.log("Transaction:", result.deployTransaction.hash); + + // Wait for half a minute for the transaction completion + await new Promise(r => setTimeout(r, 30000)); + + // Writing updated parameters back to the JSON file + parsedData.baseTargetDispenserL2Address = baseTargetDispenserL2.address; + fs.writeFileSync(globalsFile, JSON.stringify(parsedData)); + + // Contract verification + if (parsedData.contractVerification) { + const execSync = require("child_process").execSync; + execSync("npx hardhat verify --constructor-args scripts/deployment/staking/optimistic/verify_07_base_target_dispenser.js --network " + providerName + " " + baseTargetDispenserL2.address, { encoding: "utf-8" }); + } +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/scripts/deployment/staking/base/deploy_71_change_owner.js b/scripts/deployment/staking/base/deploy_71_change_owner.js new file mode 100644 index 00000000..d959f2e7 --- /dev/null +++ b/scripts/deployment/staking/base/deploy_71_change_owner.js @@ -0,0 +1,48 @@ +/*global process*/ + +const { ethers } = require("hardhat"); +const { LedgerSigner } = require("@anders-t/ethers-ledger"); + +async function main() { + const fs = require("fs"); + const globalsFile = "globals.json"; + const dataFromJSON = fs.readFileSync(globalsFile, "utf8"); + let parsedData = JSON.parse(dataFromJSON); + const useLedger = parsedData.useLedger; + const derivationPath = parsedData.derivationPath; + const providerName = parsedData.providerName; + const baseTargetDispenserL2Address = parsedData.baseTargetDispenserL2Address; + const bridgeMediatorAddress = parsedData.bridgeMediatorAddress; + + let networkURL = parsedData.networkURL; + const provider = new ethers.providers.JsonRpcProvider(networkURL); + const signers = await ethers.getSigners(); + + let EOA; + if (useLedger) { + EOA = new LedgerSigner(provider, derivationPath); + } else { + EOA = signers[0]; + } + // EOA address + const deployer = await EOA.getAddress(); + console.log("EOA is:", deployer); + + // Transaction signing and execution + console.log("71. EOA to change owner in OptimismTargetDispenserL2 (Base)"); + const baseTargetDispenserL2 = await ethers.getContractAt("OptimismTargetDispenserL2", baseTargetDispenserL2Address); + console.log("You are signing the following transaction: OptimismTargetDispenserL2.connect(EOA).changeOwner()"); + const result = await baseTargetDispenserL2.connect(EOA).changeOwner(bridgeMediatorAddress); + + // Transaction details + console.log("Contract deployment: OptimismTargetDispenserL2"); + console.log("Contract address:", baseTargetDispenserL2.address); + console.log("Transaction:", result.hash); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/scripts/deployment/staking/base/globals_base_mainnet.json b/scripts/deployment/staking/base/globals_base_mainnet.json new file mode 100644 index 00000000..0feae934 --- /dev/null +++ b/scripts/deployment/staking/base/globals_base_mainnet.json @@ -0,0 +1 @@ +{"contractVerification":true,"useLedger":true,"derivationPath":"m/44'/60'/2'/0/0","providerName":"base","networkURL":"https://mainnet.base.org","gasPriceInGwei":"2","olasAddress":"0x54330d28ca3357F294334BDC454a032e7f353416","serviceStakingFactoryAddress":"0x1cEe30D08943EB58EFF84DD1AB44a6ee6FEff63a","bridgeMediatorAddress":"0xE49CB081e8d96920C38aA7AB90cb0294ab4Bc8EA","baseL2CrossDomainMessengerAddress":"0x4200000000000000000000000000000000000007","l1ChainId":"1","baseDepositProcessorL1Address":"0x42BA1BbD797E4C90F386F03a544F3b62C1f917d0","baseTargetDispenserL2Address":"0xcDdD9D9ABaB36fFa882530D69c73FeE5D4001C2d"} \ No newline at end of file diff --git a/scripts/deployment/staking/base/verify_07_base_target_dispenser.js b/scripts/deployment/staking/base/verify_07_base_target_dispenser.js new file mode 100644 index 00000000..be0fd403 --- /dev/null +++ b/scripts/deployment/staking/base/verify_07_base_target_dispenser.js @@ -0,0 +1,12 @@ +const fs = require("fs"); +const globalsFile = "globals.json"; +const dataFromJSON = fs.readFileSync(globalsFile, "utf8"); +const parsedData = JSON.parse(dataFromJSON); + +module.exports = [ + parsedData.olasAddress, + parsedData.serviceStakingFactoryAddress, + parsedData.baseL2CrossDomainMessengerAddress, + parsedData.baseDepositProcessorL1Address, + parsedData.l1ChainId +]; \ No newline at end of file diff --git a/scripts/deployment/staking/celo/deploy_051_change_owner.js b/scripts/deployment/staking/celo/deploy_051_change_owner.js new file mode 100644 index 00000000..6ca830ec --- /dev/null +++ b/scripts/deployment/staking/celo/deploy_051_change_owner.js @@ -0,0 +1,48 @@ +/*global process*/ + +const { ethers } = require("hardhat"); +const { LedgerSigner } = require("@anders-t/ethers-ledger"); + +async function main() { + const fs = require("fs"); + const globalsFile = "globals.json"; + const dataFromJSON = fs.readFileSync(globalsFile, "utf8"); + let parsedData = JSON.parse(dataFromJSON); + const useLedger = parsedData.useLedger; + const derivationPath = parsedData.derivationPath; + const providerName = parsedData.providerName; + const celoTargetDispenserL2Address = parsedData.celoTargetDispenserL2Address; + const bridgeMediatorAddress = parsedData.bridgeMediatorAddress; + + let networkURL = parsedData.networkURL; + const provider = new ethers.providers.JsonRpcProvider(networkURL); + const signers = await ethers.getSigners(); + + let EOA; + if (useLedger) { + EOA = new LedgerSigner(provider, derivationPath); + } else { + EOA = signers[0]; + } + // EOA address + const deployer = await EOA.getAddress(); + console.log("EOA is:", deployer); + + // Transaction signing and execution + console.log("51. EOA to change owner in WormholeTargetDispenserL2 (Celo)"); + const celoTargetDispenserL2 = await ethers.getContractAt("WormholeTargetDispenserL2", celoTargetDispenserL2Address); + console.log("You are signing the following transaction: WormholeTargetDispenserL2.connect(EOA).changeOwner()"); + const result = await celoTargetDispenserL2.connect(EOA).changeOwner(bridgeMediatorAddress); + + // Transaction details + console.log("Contract deployment: WormholeTargetDispenserL2"); + console.log("Contract address:", celoTargetDispenserL2.address); + console.log("Transaction:", result.hash); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/scripts/deployment/staking/celo/deploy_05_celo_targer_dispenser.js b/scripts/deployment/staking/celo/deploy_05_celo_targer_dispenser.js new file mode 100644 index 00000000..cfe1d7b6 --- /dev/null +++ b/scripts/deployment/staking/celo/deploy_05_celo_targer_dispenser.js @@ -0,0 +1,76 @@ +/*global process*/ + +const { ethers } = require("hardhat"); +const { LedgerSigner } = require("@anders-t/ethers-ledger"); + +async function main() { + const fs = require("fs"); + const globalsFile = "globals.json"; + const dataFromJSON = fs.readFileSync(globalsFile, "utf8"); + let parsedData = JSON.parse(dataFromJSON); + const useLedger = parsedData.useLedger; + const derivationPath = parsedData.derivationPath; + const providerName = parsedData.providerName; + + let networkURL = parsedData.networkURL; + if (providerName === "polygon") { + if (!process.env.ALCHEMY_API_KEY_MATIC) { + console.log("set ALCHEMY_API_KEY_MATIC env variable"); + } + networkURL += process.env.ALCHEMY_API_KEY_MATIC; + } else if (providerName === "polygonAmoy") { + if (!process.env.ALCHEMY_API_KEY_AMOY) { + console.log("set ALCHEMY_API_KEY_AMOY env variable"); + return; + } + networkURL += process.env.ALCHEMY_API_KEY_AMOY; + } + + const provider = new ethers.providers.JsonRpcProvider(networkURL); + const signers = await ethers.getSigners(); + + let EOA; + if (useLedger) { + EOA = new LedgerSigner(provider, derivationPath); + } else { + EOA = signers[0]; + } + // EOA address + const deployer = await EOA.getAddress(); + console.log("EOA is:", deployer); + + // Transaction signing and execution + console.log("5. EOA to deploy WormholeTargetDispenserL2"); + const WormholeTargetDispenserL2 = await ethers.getContractFactory("WormholeTargetDispenserL2"); + console.log("You are signing the following transaction: WormholeTargetDispenserL2.connect(EOA).deploy()"); + const celoTargetDispenserL2 = await WormholeTargetDispenserL2.connect(EOA).deploy(parsedData.olasAddress, + parsedData.serviceStakingFactoryAddress, parsedData.wormholeL2MessageRelayer, + parsedData.celoDepositProcessorL1Address, parsedData.wormholel1ChainId, + parsedData.wormholeL2CoreAddress, parsedData.wormholeL2TokenRelayerAddress); + const result = await celoTargetDispenserL2.deployed(); + + // Transaction details + console.log("Contract deployment: WormholeTargetDispenserL2"); + console.log("Contract address:", celoTargetDispenserL2.address); + console.log("Transaction:", result.deployTransaction.hash); + + // Wait for half a minute for the transaction completion + await new Promise(r => setTimeout(r, 30000)); + + // Writing updated parameters back to the JSON file + parsedData.celoTargetDispenserL2Address = celoTargetDispenserL2.address; + fs.writeFileSync(globalsFile, JSON.stringify(parsedData)); + + // Contract verification + if (parsedData.contractVerification) { + const execSync = require("child_process").execSync; + execSync("npx hardhat verify --constructor-args scripts/deployment/staking/celo/verify_05_celo_target_dispenser.js --network " + providerName + " " + celoTargetDispenserL2.address, { encoding: "utf-8" }); + } +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/scripts/deployment/staking/celo/globals_celo_mainnet.json b/scripts/deployment/staking/celo/globals_celo_mainnet.json new file mode 100644 index 00000000..a6d7d552 --- /dev/null +++ b/scripts/deployment/staking/celo/globals_celo_mainnet.json @@ -0,0 +1 @@ +{"contractVerification":true,"useLedger":true,"derivationPath":"m/44'/60'/2'/0/0","providerName":"celo","networkURL":"https://forno.celo.org","gasPriceInGwei":"2","olasAddress":"0xaCFfAe8e57Ec6E394Eb1b41939A8CF7892DbDc51","serviceStakingFactoryAddress":"0x1c2cD884127b080F940b7546c1e9aaf525b1FA55","bridgeMediatorAddress":"0x397125902ED2cA2d42104F621f448A2cE1bC8Fb7","wormholeL2CoreAddress":"0xa321448d90d4e5b0A732867c18eA198e75CAC48E","wormholeL2TokenRelayerAddress":"0x796Dff6D74F3E27060B71255Fe517BFb23C93eed","wormholeL2MessageRelayer":"0x27428DD2d3DD32A4D7f7C497eAaa23130d894911","l1ChainId":"2","celoDepositProcessorL1Address":"0x223902b6C583f18E8dc84AF4E6a8fa523d088B78","celoTargetDispenserL2Address":"0xb4096d181C08DDF75f1A63918cCa0d1023C4e6C7"} \ No newline at end of file diff --git a/scripts/deployment/staking/wormhole/verify_05_celo_wormhole_target_dispenser.js b/scripts/deployment/staking/celo/verify_05_celo_target_dispenser.js similarity index 100% rename from scripts/deployment/staking/wormhole/verify_05_celo_wormhole_target_dispenser.js rename to scripts/deployment/staking/celo/verify_05_celo_target_dispenser.js diff --git a/scripts/deployment/staking/deploy_05_celo_wormhole_deposit_processor.js b/scripts/deployment/staking/deploy_05_celo_deposit_processor.js similarity index 81% rename from scripts/deployment/staking/deploy_05_celo_wormhole_deposit_processor.js rename to scripts/deployment/staking/deploy_05_celo_deposit_processor.js index 43d8d473..e1aab94e 100644 --- a/scripts/deployment/staking/deploy_05_celo_wormhole_deposit_processor.js +++ b/scripts/deployment/staking/deploy_05_celo_deposit_processor.js @@ -29,15 +29,15 @@ async function main() { console.log("5. EOA to deploy WormholeDepositProcessorL1"); const WormholeDepositProcessorL1 = await ethers.getContractFactory("WormholeDepositProcessorL1"); console.log("You are signing the following transaction: WormholeDepositProcessorL1.connect(EOA).deploy()"); - const wormholeDepositProcessorL1 = await WormholeDepositProcessorL1.connect(EOA).deploy(parsedData.olasAddress, + const celoDepositProcessorL1 = await WormholeDepositProcessorL1.connect(EOA).deploy(parsedData.olasAddress, parsedData.dispenserAddress, parsedData.wormholeL1TokenRelayerAddress, parsedData.wormholeL1MessageRelayerAddress, parsedData.celoL2TargetChainId, parsedData.wormholeL1CoreAddress, parsedData.celoWormholeL2TargetChainId); - const result = await wormholeDepositProcessorL1.deployed(); + const result = await celoDepositProcessorL1.deployed(); // Transaction details console.log("Contract deployment: WormholeDepositProcessorL1"); - console.log("Contract address:", wormholeDepositProcessorL1.address); + console.log("Contract address:", celoDepositProcessorL1.address); console.log("Transaction:", result.deployTransaction.hash); // If on sepolia, wait a minute for the transaction completion @@ -46,13 +46,13 @@ async function main() { } // Writing updated parameters back to the JSON file - parsedData.wormholeDepositProcessorL1Address = wormholeDepositProcessorL1.address; + parsedData.celoDepositProcessorL1Address = celoDepositProcessorL1.address; fs.writeFileSync(globalsFile, JSON.stringify(parsedData)); // Contract verification if (parsedData.contractVerification) { const execSync = require("child_process").execSync; - execSync("npx hardhat verify --constructor-args scripts/deployment/staking/verify_05_wormhole_deposit_processor.js --network " + providerName + " " + wormholeDepositProcessorL1.address, { encoding: "utf-8" }); + execSync("npx hardhat verify --constructor-args scripts/deployment/staking/verify_05_celo_deposit_processor.js --network " + providerName + " " + celoDepositProcessorL1.address, { encoding: "utf-8" }); } } diff --git a/scripts/deployment/staking/deploy_07_base_deposit_processor.js b/scripts/deployment/staking/deploy_07_base_deposit_processor.js new file mode 100644 index 00000000..b2ce30d3 --- /dev/null +++ b/scripts/deployment/staking/deploy_07_base_deposit_processor.js @@ -0,0 +1,64 @@ +/*global process*/ + +const { ethers } = require("hardhat"); +const { LedgerSigner } = require("@anders-t/ethers-ledger"); + +async function main() { + const fs = require("fs"); + const globalsFile = "globals.json"; + const dataFromJSON = fs.readFileSync(globalsFile, "utf8"); + let parsedData = JSON.parse(dataFromJSON); + const useLedger = parsedData.useLedger; + const derivationPath = parsedData.derivationPath; + const providerName = parsedData.providerName; + let EOA; + + const provider = await ethers.providers.getDefaultProvider(providerName); + const signers = await ethers.getSigners(); + + if (useLedger) { + EOA = new LedgerSigner(provider, derivationPath); + } else { + EOA = signers[0]; + } + // EOA address + const deployer = await EOA.getAddress(); + console.log("EOA is:", deployer); + + // Transaction signing and execution + console.log("7. EOA to deploy OptimismDepositProcessorL1 for Base"); + const OptimismDepositProcessorL1 = await ethers.getContractFactory("OptimismDepositProcessorL1"); + console.log("You are signing the following transaction: OptimismDepositProcessorL1.connect(EOA).deploy()"); + const baseDepositProcessorL1 = await OptimismDepositProcessorL1.connect(EOA).deploy(parsedData.olasAddress, + parsedData.dispenserAddress, parsedData.baseL1StandardBridgeProxyAddress, + parsedData.baseL1CrossDomainMessengerProxyAddress, parsedData.baseL2TargetChainId, + parsedData.baseOLASAddress); + const result = await baseDepositProcessorL1.deployed(); + + // Transaction details + console.log("Contract deployment: OptimismDepositProcessorL1"); + console.log("Contract address:", baseDepositProcessorL1.address); + console.log("Transaction:", result.deployTransaction.hash); + + // If on sepolia, wait a minute for the transaction completion + if (providerName === "sepolia") { + await new Promise(r => setTimeout(r, 30000)); + } + + // Writing updated parameters back to the JSON file + parsedData.baseDepositProcessorL1Address = baseDepositProcessorL1.address; + fs.writeFileSync(globalsFile, JSON.stringify(parsedData)); + + // Contract verification + if (parsedData.contractVerification) { + const execSync = require("child_process").execSync; + execSync("npx hardhat verify --constructor-args scripts/deployment/staking/verify_07_base_deposit_processor.js --network " + providerName + " " + baseDepositProcessorL1.address, { encoding: "utf-8" }); + } +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/scripts/deployment/staking/deploy_08_ethereum_deposit_processor.js b/scripts/deployment/staking/deploy_08_ethereum_deposit_processor.js new file mode 100644 index 00000000..7a7b3e8a --- /dev/null +++ b/scripts/deployment/staking/deploy_08_ethereum_deposit_processor.js @@ -0,0 +1,62 @@ +/*global process*/ + +const { ethers } = require("hardhat"); +const { LedgerSigner } = require("@anders-t/ethers-ledger"); + +async function main() { + const fs = require("fs"); + const globalsFile = "globals.json"; + const dataFromJSON = fs.readFileSync(globalsFile, "utf8"); + let parsedData = JSON.parse(dataFromJSON); + const useLedger = parsedData.useLedger; + const derivationPath = parsedData.derivationPath; + const providerName = parsedData.providerName; + let EOA; + + const provider = await ethers.providers.getDefaultProvider(providerName); + const signers = await ethers.getSigners(); + + if (useLedger) { + EOA = new LedgerSigner(provider, derivationPath); + } else { + EOA = signers[0]; + } + // EOA address + const deployer = await EOA.getAddress(); + console.log("EOA is:", deployer); + + // Transaction signing and execution + console.log("8. EOA to deploy EthereumDepositProcessor for Base"); + const EthereumDepositProcessor = await ethers.getContractFactory("EthereumDepositProcessor"); + console.log("You are signing the following transaction: EthereumDepositProcessor.connect(EOA).deploy()"); + const ethereumDepositProcessor = await EthereumDepositProcessor.connect(EOA).deploy(parsedData.olasAddress, + parsedData.dispenserAddress, parsedData.serviceStakingFactoryAddress, parsedData.timelockAddress); + const result = await ethereumDepositProcessor.deployed(); + + // Transaction details + console.log("Contract deployment: EthereumDepositProcessor"); + console.log("Contract address:", ethereumDepositProcessor.address); + console.log("Transaction:", result.deployTransaction.hash); + + // If on sepolia, wait a minute for the transaction completion + if (providerName === "sepolia") { + await new Promise(r => setTimeout(r, 30000)); + } + + // Writing updated parameters back to the JSON file + parsedData.ethereumDepositProcessorAddress = ethereumDepositProcessor.address; + fs.writeFileSync(globalsFile, JSON.stringify(parsedData)); + + // Contract verification + if (parsedData.contractVerification) { + const execSync = require("child_process").execSync; + execSync("npx hardhat verify --constructor-args scripts/deployment/staking/verify_08_ethereum_deposit_processor.js --network " + providerName + " " + ethereumDepositProcessor.address, { encoding: "utf-8" }); + } +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/scripts/deployment/staking/deploy_09_set_targer_dispensers.js b/scripts/deployment/staking/deploy_09_set_targer_dispensers.js new file mode 100644 index 00000000..95871b3e --- /dev/null +++ b/scripts/deployment/staking/deploy_09_set_targer_dispensers.js @@ -0,0 +1,81 @@ +/*global process*/ + +const { ethers } = require("hardhat"); +const { LedgerSigner } = require("@anders-t/ethers-ledger"); + +async function main() { + const fs = require("fs"); + const globalsFile = "globals.json"; + const dataFromJSON = fs.readFileSync(globalsFile, "utf8"); + let parsedData = JSON.parse(dataFromJSON); + const useLedger = parsedData.useLedger; + const derivationPath = parsedData.derivationPath; + const providerName = parsedData.providerName; + const arbitrumDepositProcessorL1Address = parsedData.arbitrumDepositProcessorL1Address; + const arbitrumTargetDispenserL2Address = parsedData.arbitrumTargetDispenserL2Address; + const baseDepositProcessorL1Address = parsedData.baseDepositProcessorL1Address; + const baseTargetDispenserL2Address = parsedData.baseTargetDispenserL2Address; + const celoDepositProcessorL1Address = parsedData.celoDepositProcessorL1Address; + const celoTargetDispenserL2Address = parsedData.celoTargetDispenserL2Address; + const gnosisDepositProcessorL1Address = parsedData.gnosisDepositProcessorL1Address; + const gnosisTargetDispenserL2Address = parsedData.gnosisTargetDispenserL2Address; + const optimismDepositProcessorL1Address = parsedData.optimismDepositProcessorL1Address; + const optimismTargetDispenserL2Address = parsedData.optimismTargetDispenserL2Address; + const polygonDepositProcessorL1Address = parsedData.polygonDepositProcessorL1Address; + const polygonTargetDispenserL2Address = parsedData.polygonTargetDispenserL2Address; + let EOA; + + const provider = await ethers.providers.getDefaultProvider(providerName); + const signers = await ethers.getSigners(); + + if (useLedger) { + EOA = new LedgerSigner(provider, derivationPath); + } else { + EOA = signers[0]; + } + // EOA address + const deployer = await EOA.getAddress(); + console.log("EOA is:", deployer); + + // Get all the contracts + const arbitrumDepositProcessorL1 = await ethers.getContractAt("ArbitrumDepositProcessorL1", arbitrumDepositProcessorL1Address); + const baseDepositProcessorL1 = await ethers.getContractAt("OptimismDepositProcessorL1", baseDepositProcessorL1Address); + const celoDepositProcessorL1 = await ethers.getContractAt("WormholeDepositProcessorL1", celoDepositProcessorL1Address); + const gnosisDepositProcessorL1 = await ethers.getContractAt("GnosisDepositProcessorL1", gnosisDepositProcessorL1Address); + const optimismDepositProcessorL1 = await ethers.getContractAt("OptimismDepositProcessorL1", optimismDepositProcessorL1Address); + const polygonDepositProcessorL1 = await ethers.getContractAt("PolygonDepositProcessorL1", polygonDepositProcessorL1Address); + + // Transaction signing and execution + console.log("9. EOA to set TargetDispenserL2 in DepositProcessorL1-s"); + + console.log("You are signing the following transaction: ArbitrumDepositProcessorL1.connect(EOA).setL2TargetDispenser()"); + let result = await arbitrumDepositProcessorL1.connect(EOA).setL2TargetDispenser(arbitrumTargetDispenserL2Address); + console.log("Transaction:", result.hash); + + console.log("You are signing the following transaction: OptimismDepositProcessorL1.connect(EOA).setL2TargetDispenser()"); + result = await baseDepositProcessorL1.connect(EOA).setL2TargetDispenser(baseTargetDispenserL2Address); + console.log("Transaction:", result.hash); + + console.log("You are signing the following transaction: WormholeDepositProcessorL1.connect(EOA).setL2TargetDispenser()"); + result = await celoDepositProcessorL1.connect(EOA).setL2TargetDispenser(celoTargetDispenserL2Address); + console.log("Transaction:", result.hash); + + console.log("You are signing the following transaction: GnosisDepositProcessorL1.connect(EOA).setL2TargetDispenser()"); + result = await gnosisDepositProcessorL1.connect(EOA).setL2TargetDispenser(gnosisTargetDispenserL2Address); + console.log("Transaction:", result.hash); + + console.log("You are signing the following transaction: OptimismDepositProcessorL1.connect(EOA).setL2TargetDispenser()"); + result = await optimismDepositProcessorL1.connect(EOA).setL2TargetDispenser(optimismTargetDispenserL2Address); + console.log("Transaction:", result.hash); + + console.log("You are signing the following transaction: PolygonDepositProcessorL1.connect(EOA).setL2TargetDispenser()"); + result = await polygonDepositProcessorL1.connect(EOA).setL2TargetDispenser(polygonTargetDispenserL2Address); + console.log("Transaction:", result.hash); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/scripts/deployment/staking/deploy_10_set_deposit_processors.js b/scripts/deployment/staking/deploy_10_set_deposit_processors.js new file mode 100644 index 00000000..ddc68cff --- /dev/null +++ b/scripts/deployment/staking/deploy_10_set_deposit_processors.js @@ -0,0 +1,62 @@ +/*global process*/ + +const { ethers } = require("hardhat"); +const { LedgerSigner } = require("@anders-t/ethers-ledger"); + +async function main() { + const fs = require("fs"); + const globalsFile = "globals.json"; + const dataFromJSON = fs.readFileSync(globalsFile, "utf8"); + let parsedData = JSON.parse(dataFromJSON); + const useLedger = parsedData.useLedger; + const derivationPath = parsedData.derivationPath; + const providerName = parsedData.providerName; + const arbitrumDepositProcessorL1Address = parsedData.arbitrumDepositProcessorL1Address; + const baseDepositProcessorL1Address = parsedData.baseDepositProcessorL1Address; + const celoDepositProcessorL1Address = parsedData.celoDepositProcessorL1Address; + const gnosisDepositProcessorL1Address = parsedData.gnosisDepositProcessorL1Address; + const optimismDepositProcessorL1Address = parsedData.optimismDepositProcessorL1Address; + const polygonDepositProcessorL1Address = parsedData.polygonDepositProcessorL1Address; + const ethereumDepositProcessorAddress = parsedData.ethereumDepositProcessorAddress; + const dispenserAddress = parsedData.dispenserAddress; + let EOA; + + const provider = await ethers.providers.getDefaultProvider(providerName); + const signers = await ethers.getSigners(); + + if (useLedger) { + EOA = new LedgerSigner(provider, derivationPath); + } else { + EOA = signers[0]; + } + // EOA address + const deployer = await EOA.getAddress(); + console.log("EOA is:", deployer); + + // Get all the contracts + const arbitrumDepositProcessorL1 = await ethers.getContractAt("ArbitrumDepositProcessorL1", arbitrumDepositProcessorL1Address); + const baseDepositProcessorL1 = await ethers.getContractAt("OptimismDepositProcessorL1", baseDepositProcessorL1Address); + const celoDepositProcessorL1 = await ethers.getContractAt("WormholeDepositProcessorL1", celoDepositProcessorL1Address); + const gnosisDepositProcessorL1 = await ethers.getContractAt("GnosisDepositProcessorL1", gnosisDepositProcessorL1Address); + const optimismDepositProcessorL1 = await ethers.getContractAt("OptimismDepositProcessorL1", optimismDepositProcessorL1Address); + const polygonDepositProcessorL1 = await ethers.getContractAt("PolygonDepositProcessorL1", polygonDepositProcessorL1Address); + const dispenser = await ethers.getContractAt("Dispenser", dispenserAddress); + + // Transaction signing and execution + console.log("10. EOA to set deposit processors in Dispenser"); + console.log("You are signing the following transaction: Dispenser.connect(EOA).setDepositProcessorChainIds()"); + const ethereumChainId = (await provider.getNetwork()).chainId; + const result = await dispenser.connect(EOA).setDepositProcessorChainIds([arbitrumDepositProcessorL1Address, + baseDepositProcessorL1Address, celoDepositProcessorL1Address, ethereumDepositProcessorAddress, + gnosisDepositProcessorL1Address, optimismDepositProcessorL1Address, polygonDepositProcessorL1Address], + [parsedData.arbitrumL2TargetChainId, parsedData.baseL2TargetChainId, parsedData.celoL2TargetChainId, ethereumChainId, + parsedData.gnosisL2TargetChainId, parsedData.optimisticL2TargetChainId, parsedData.polygonL2TargetChainId]); + console.log("Transaction:", result.hash); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/scripts/deployment/staking/globals_mainnet.json b/scripts/deployment/staking/globals_mainnet.json new file mode 100644 index 00000000..f39c24d8 --- /dev/null +++ b/scripts/deployment/staking/globals_mainnet.json @@ -0,0 +1 @@ +{"contractVerification":true,"useLedger":true,"derivationPath":"m/44'/60'/2'/0/0","providerName":"mainnet","olasAddress":"0x0001A500A6B18995B03f44bb040A5fFc28E45CB0","timelockAddress":"0x3C1fF68f5aa342D296d4DEe4Bb1cACCA912D95fE","dispenserAddress":"0x5650300fCBab43A0D7D02F8Cb5d0f039402593f0","arbitrumL1ERC20GatewayRouterAddress":"0x72Ce9c846789fdB6fC1f34aC4AD25Dd9ef7031ef","arbitrumL1ERC20GatewayAddress":"0xa3A7B6F88361F48403514059F1F16C8E78d60EeC","arbitrumInboxAddress":"0x4Dbd4fc535Ac27206064B68FfCf827b0A60BAB3f","arbitrumOutboxAddress":"0x0B9857ae2D4A3DBe74ffE1d7DF045bb7F96E4840","arbitrumBridgeAddress":"0x8315177aB297bA92A06054cE80a67Ed4DBd7ed3a","arbitrumL2TargetChainId":"42161","arbitrumDepositProcessorL1Address":"0x5e13E07006D68B097DCb5979ef5545C4f9156162","gnosisOmniBridgeAddress":"0x88ad09518695c6c3712AC10a214bE5109a655671","gnosisAMBForeignAddress":"0x4C36d2919e407f0Cc2Ee3c993ccF8ac26d9CE64e","gnosisL2TargetChainId":"100","gnosisDepositProcessorL1Address":"0xEEf2c02cFC445bFFf1c891D486424Ef3aBc66AB0","optimisticL1StandardBridgeProxyAddress":"0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1","optimisticL1CrossDomainMessengerProxyAddress":"0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1","optimisticOLASAddress":"0xFC2E6e6BCbd49ccf3A5f029c79984372DcBFE527","optimisticL2TargetChainId":"10","optimismDepositProcessorL1Address":"0xAB787ceebe8F2b8dca44e3bB744D6e63003ee978","wormholeL1CoreAddress":"0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B","wormholeL1TokenRelayerAddress":"0x3ee18B2214AFF97000D974cf647E7C347E8fa585","wormholeL1MessageRelayerAddress":"0x27428DD2d3DD32A4D7f7C497eAaa23130d894911","celoL2TargetChainId":"42220","celoWormholeL2TargetChainId":"14","celoDepositProcessorL1Address":"0x223902b6C583f18E8dc84AF4E6a8fa523d088B78","polygonRootChainManagerProxyAddress":"0xA0c68C638235ee32657e8f720a23ceC1bFc77C77","polygonFXRootAddress":"0xfe5e5D361b2ad62c541bAb87C45a0B9B018389a2","polygonCheckpointManagerAddress":"0x86E4Dc95c7FBdBf52e33D563BbDB00823894C287","polygonERC20PredicateAddress":"0x40ec5B33f54e0E8A33A975908C5BA1c14e5BbbDf","polygonL2TargetChainId":"137","polygonDepositProcessorL1Address":"0x4Ce43b82EF1298E1466D3b3Cee67BA6680bF82FB","baseL1StandardBridgeProxyAddress":"0x3154Cf16ccdb4C6d922629664174b904d80F2C35","baseL1CrossDomainMessengerProxyAddress":"0x866E82a600A1414e583f7F13623F1aC5d58b0Afa","baseOLASAddress":"0x54330d28ca3357F294334BDC454a032e7f353416","baseL2TargetChainId":"8453","baseDepositProcessorL1Address":"0x42BA1BbD797E4C90F386F03a544F3b62C1f917d0","serviceStakingFactoryAddress":"0xEBdde456EA288b49f7D5975E7659bA1Ccf607efc","ethereumDepositProcessorAddress":"0x15CD7fAeE048c7673aB818C9e582630F1a924593","arbitrumTargetDispenserL2Address":"0x10c5525F77F13b28f42c5626240c001c2D57CAd4","baseTargetDispenserL2Address":"0xcDdD9D9ABaB36fFa882530D69c73FeE5D4001C2d","celoTargetDispenserL2Address":"0xb4096d181C08DDF75f1A63918cCa0d1023C4e6C7","gnosisTargetDispenserL2Address":"0x67722c823010CEb4BED5325fE109196C0f67D053","optimismTargetDispenserL2Address":"0x04b0007b2aFb398015B76e5f22993a1fddF83644","polygonTargetDispenserL2Address":"0xf76953444C35F1FcE2F6CA1b167173357d3F5C17"} \ No newline at end of file diff --git a/scripts/deployment/staking/globals_sepolia.json b/scripts/deployment/staking/globals_sepolia.json index 7b1f6dda..78d3a9ee 100644 --- a/scripts/deployment/staking/globals_sepolia.json +++ b/scripts/deployment/staking/globals_sepolia.json @@ -1 +1 @@ -{"contractVerification":true,"useLedger":false,"derivationPath":"m/44'/60'/2'/0/0","providerName":"sepolia","olasAddress":"0xeb2725bD76f6b1569Cf1484fCa0f2D55714A085d","dispenserAddress":"0x42f43be9E5E50df51b86C5c6427223ff565f40C6","arbitrumL1ERC20GatewayRouterAddress":"0xcE18836b233C83325Cc8848CA4487e94C6288264","arbitrumL1ERC20GatewayAddress":"0x902b3E5f8F19571859F4AB1003B960a5dF693aFF","arbitrumInboxAddress":"0xaAe29B0366299461418F5324a79Afc425BE5ae21","arbitrumOutboxAddress":"0x65f07C7D521164a4d5DaC6eB8Fac8DA067A3B78F","arbitrumBridgeAddress":"0x38f918D0E9F1b721EDaA41302E399fa1B79333a9","arbitrumL2TargetChainId":"421614","arbitrumDepositProcessorL1Address":"0xACd410f51DA5aAe1fF925565FBCB6B6eedbB00E2","gnosisOmniBridgeAddress":"0x63E47C5e3303DDDCaF3b404B1CCf9Eb633652e9e","gnosisAMBForeignAddress":"0xf2546D6648BD2af6a008A7e7C1542BB240329E11","gnosisL2TargetChainId":"10200","gnosisDepositProcessorL1Address":"0x679Ce81a7bab6808534137585850dc81F90Ea8a4","optimisticL1StandardBridgeProxyAddress":"0xFBb0621E0B23b5478B630BD55a5f21f67730B0F1","optimisticL1CrossDomainMessengerProxyAddress":"0x58Cc85b8D04EA49cC6DBd3CbFFd00B4B8D6cb3ef","optimisticOLASAddress":"0x01B8b6384298D4848E3BE63D4C9D17830EeE488A","optimisticL2TargetChainId":"11155420","optimismDepositProcessorL1Address":"0xDc6B77e32e751C7d6e1d1c39A64c64a8F0049E21","wormholeL1CoreAddress":"0x4a8bc80Ed5a4067f1CCf107057b8270E0cC11A78","wormholeL1TokenRelayerAddress":"0xDB5492265f6038831E89f495670FF909aDe94bd9","wormholeL1MessageRelayerAddress":"0x7B1bD7a6b4E61c2a123AC6BC2cbfC614437D0470","celoL2TargetChainId":"44787","celoWormholeL2TargetChainId":"14","celoWormholeDepositProcessorL1Address":"","polygonRootChainManagerProxyAddress":"0x34F5A25B627f50Bb3f5cAb72807c4D4F405a9232","polygonFXRootAddress":"0x0E13EBEdDb8cf9f5987512d5E081FdC2F5b0991e","polygonCheckpointManagerAddress":"0xbd07D7E1E93c8d4b2a261327F3C28a8EA7167209","polygonERC20PredicateAddress":"0x4258c75b752c812b7fa586bdeb259f2d4bd17f4f","polygonL2TargetChainId":"80002","polygonDepositProcessorL1Address":"0x36c1beAFBeaf65DFcF16De60867BF9525455bf4E"} \ No newline at end of file +{"contractVerification":true,"useLedger":false,"derivationPath":"m/44'/60'/2'/0/0","providerName":"sepolia","olasAddress":"0xeb2725bD76f6b1569Cf1484fCa0f2D55714A085d","timelockAddress":"0x3C1fF68f5aa342D296d4DEe4Bb1cACCA912D95fE","dispenserAddress":"0x42f43be9E5E50df51b86C5c6427223ff565f40C6","arbitrumL1ERC20GatewayRouterAddress":"0xcE18836b233C83325Cc8848CA4487e94C6288264","arbitrumL1ERC20GatewayAddress":"0x902b3E5f8F19571859F4AB1003B960a5dF693aFF","arbitrumInboxAddress":"0xaAe29B0366299461418F5324a79Afc425BE5ae21","arbitrumOutboxAddress":"0x65f07C7D521164a4d5DaC6eB8Fac8DA067A3B78F","arbitrumBridgeAddress":"0x38f918D0E9F1b721EDaA41302E399fa1B79333a9","arbitrumL2TargetChainId":"421614","arbitrumDepositProcessorL1Address":"0xACd410f51DA5aAe1fF925565FBCB6B6eedbB00E2","gnosisOmniBridgeAddress":"0x63E47C5e3303DDDCaF3b404B1CCf9Eb633652e9e","gnosisAMBForeignAddress":"0xf2546D6648BD2af6a008A7e7C1542BB240329E11","gnosisL2TargetChainId":"10200","gnosisDepositProcessorL1Address":"0x679Ce81a7bab6808534137585850dc81F90Ea8a4","optimisticL1StandardBridgeProxyAddress":"0xFBb0621E0B23b5478B630BD55a5f21f67730B0F1","optimisticL1CrossDomainMessengerProxyAddress":"0x58Cc85b8D04EA49cC6DBd3CbFFd00B4B8D6cb3ef","optimisticOLASAddress":"0x01B8b6384298D4848E3BE63D4C9D17830EeE488A","optimisticL2TargetChainId":"11155420","optimismDepositProcessorL1Address":"0xDc6B77e32e751C7d6e1d1c39A64c64a8F0049E21","wormholeL1CoreAddress":"0x4a8bc80Ed5a4067f1CCf107057b8270E0cC11A78","wormholeL1TokenRelayerAddress":"0xDB5492265f6038831E89f495670FF909aDe94bd9","wormholeL1MessageRelayerAddress":"0x7B1bD7a6b4E61c2a123AC6BC2cbfC614437D0470","celoL2TargetChainId":"44787","celoWormholeL2TargetChainId":"14","celoWormholeDepositProcessorL1Address":"","polygonRootChainManagerProxyAddress":"0x34F5A25B627f50Bb3f5cAb72807c4D4F405a9232","polygonFXRootAddress":"0x0E13EBEdDb8cf9f5987512d5E081FdC2F5b0991e","polygonCheckpointManagerAddress":"0xbd07D7E1E93c8d4b2a261327F3C28a8EA7167209","polygonERC20PredicateAddress":"0x4258c75b752c812b7fa586bdeb259f2d4bd17f4f","polygonL2TargetChainId":"80002","polygonDepositProcessorL1Address":"0x36c1beAFBeaf65DFcF16De60867BF9525455bf4E","serviceStakingFactoryAddress":"0x01187451346d46D6fd2e6647a2980E0d6C06d4Da"} \ No newline at end of file diff --git a/scripts/deployment/staking/gnosis/deploy_031_change_owner.js b/scripts/deployment/staking/gnosis/deploy_031_change_owner.js new file mode 100644 index 00000000..5170247f --- /dev/null +++ b/scripts/deployment/staking/gnosis/deploy_031_change_owner.js @@ -0,0 +1,48 @@ +/*global process*/ + +const { ethers } = require("hardhat"); +const { LedgerSigner } = require("@anders-t/ethers-ledger"); + +async function main() { + const fs = require("fs"); + const globalsFile = "globals.json"; + const dataFromJSON = fs.readFileSync(globalsFile, "utf8"); + let parsedData = JSON.parse(dataFromJSON); + const useLedger = parsedData.useLedger; + const derivationPath = parsedData.derivationPath; + const providerName = parsedData.providerName; + const gnosisTargetDispenserL2Address = parsedData.gnosisTargetDispenserL2Address; + const bridgeMediatorAddress = parsedData.bridgeMediatorAddress; + + let networkURL = parsedData.networkURL; + const provider = new ethers.providers.JsonRpcProvider(networkURL); + const signers = await ethers.getSigners(); + + let EOA; + if (useLedger) { + EOA = new LedgerSigner(provider, derivationPath); + } else { + EOA = signers[0]; + } + // EOA address + const deployer = await EOA.getAddress(); + console.log("EOA is:", deployer); + + // Transaction signing and execution + console.log("31. EOA to change owner in GnosisTargetDispenserL2"); + const gnosisTargetDispenserL2 = await ethers.getContractAt("GnosisTargetDispenserL2", gnosisTargetDispenserL2Address); + console.log("You are signing the following transaction: GnosisTargetDispenserL2.connect(EOA).changeOwner()"); + const result = await gnosisTargetDispenserL2.connect(EOA).changeOwner(bridgeMediatorAddress); + + // Transaction details + console.log("Contract deployment: GnosisTargetDispenserL2"); + console.log("Contract address:", gnosisTargetDispenserL2.address); + console.log("Transaction:", result.hash); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/scripts/deployment/staking/gnosis/globals_gnosis_mainnet.json b/scripts/deployment/staking/gnosis/globals_gnosis_mainnet.json new file mode 100644 index 00000000..8697e959 --- /dev/null +++ b/scripts/deployment/staking/gnosis/globals_gnosis_mainnet.json @@ -0,0 +1 @@ +{"contractVerification":true,"useLedger":true,"derivationPath":"m/44'/60'/2'/0/0","providerName":"gnosis","networkURL":"https://rpc.gnosischain.com","gasPriceInGwei":"5","olasAddress":"0xcE11e14225575945b8E6Dc0D4F2dD4C570f79d9f","serviceStakingFactoryAddress":"0xb0228CA253A88Bc8eb4ca70BCAC8f87b381f4700","bridgeMediatorAddress":"0x15bd56669F57192a97dF41A2aa8f4403e9491776","gnosisAMBHomeAddress":"0x75Df5AF045d91108662D8080fD1FEFAd6aA0bb59","l1ChainId":"1","gnosisDepositProcessorL1Address":"0xEEf2c02cFC445bFFf1c891D486424Ef3aBc66AB0","gnosisTargetDispenserL2Address":"0x67722c823010CEb4BED5325fE109196C0f67D053"} \ No newline at end of file diff --git a/scripts/deployment/staking/optimistic/deploy_41_change_owner.js b/scripts/deployment/staking/optimistic/deploy_41_change_owner.js new file mode 100644 index 00000000..5213fc69 --- /dev/null +++ b/scripts/deployment/staking/optimistic/deploy_41_change_owner.js @@ -0,0 +1,48 @@ +/*global process*/ + +const { ethers } = require("hardhat"); +const { LedgerSigner } = require("@anders-t/ethers-ledger"); + +async function main() { + const fs = require("fs"); + const globalsFile = "globals.json"; + const dataFromJSON = fs.readFileSync(globalsFile, "utf8"); + let parsedData = JSON.parse(dataFromJSON); + const useLedger = parsedData.useLedger; + const derivationPath = parsedData.derivationPath; + const providerName = parsedData.providerName; + const optimismTargetDispenserL2Address = parsedData.optimismTargetDispenserL2Address; + const bridgeMediatorAddress = parsedData.bridgeMediatorAddress; + + let networkURL = parsedData.networkURL; + const provider = new ethers.providers.JsonRpcProvider(networkURL); + const signers = await ethers.getSigners(); + + let EOA; + if (useLedger) { + EOA = new LedgerSigner(provider, derivationPath); + } else { + EOA = signers[0]; + } + // EOA address + const deployer = await EOA.getAddress(); + console.log("EOA is:", deployer); + + // Transaction signing and execution + console.log("41. EOA to change owner in OptimismTargetDispenserL2"); + const optimismTargetDispenserL2 = await ethers.getContractAt("OptimismTargetDispenserL2", optimismTargetDispenserL2Address); + console.log("You are signing the following transaction: OptimismTargetDispenserL2.connect(EOA).changeOwner()"); + const result = await optimismTargetDispenserL2.connect(EOA).changeOwner(bridgeMediatorAddress); + + // Transaction details + console.log("Contract deployment: OptimismTargetDispenserL2"); + console.log("Contract address:", optimismTargetDispenserL2.address); + console.log("Transaction:", result.hash); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/scripts/deployment/staking/optimistic/globals_optimistic_mainnet.json b/scripts/deployment/staking/optimistic/globals_optimistic_mainnet.json new file mode 100644 index 00000000..d8a04c79 --- /dev/null +++ b/scripts/deployment/staking/optimistic/globals_optimistic_mainnet.json @@ -0,0 +1 @@ +{"contractVerification":true,"useLedger":true,"derivationPath":"m/44'/60'/2'/0/0","providerName":"optimistic","networkURL":"https://optimism.drpc.org","gasPriceInGwei":"2","olasAddress":"0xFC2E6e6BCbd49ccf3A5f029c79984372DcBFE527","serviceStakingFactoryAddress":"0xa45E64d13A30a51b91ae0eb182e88a40e9b18eD8","bridgeMediatorAddress":"0x87c511c8aE3fAF0063b3F3CF9C6ab96c4AA5C60c","optimisticL2CrossDomainMessengerAddress":"0x4200000000000000000000000000000000000007","l1ChainId":"1","optimismDepositProcessorL1Address":"0xAB787ceebe8F2b8dca44e3bB744D6e63003ee978","optimismTargetDispenserL2Address":"0x04b0007b2aFb398015B76e5f22993a1fddF83644"} \ No newline at end of file diff --git a/scripts/deployment/staking/optimistic/send_tokens_and_message.js b/scripts/deployment/staking/optimistic/send_tokens_and_message.js index cc8c1dc9..23433dd7 100644 --- a/scripts/deployment/staking/optimistic/send_tokens_and_message.js +++ b/scripts/deployment/staking/optimistic/send_tokens_and_message.js @@ -55,7 +55,7 @@ const main = async () => { await tx.wait(); // tx back: https://sepolia-optimism.etherscan.io/tx/0x08ff60b3ef506e0f34e5941953608fa5bec1a13d7e0a175084245aa622edf7e0 - // tx result: + // tx result: https://sepolia.etherscan.io/tx/0xcd6ad253a6f869899f25f5d69d8261dbabd1fe49d9fce69cbcd3672064bb49dc // https://docs.optimism.io/builders/app-developers/tutorials/cross-dom-solidity#interact-with-the-l2-greeter // https://github.com/t4sk/notes/tree/main/op diff --git a/scripts/deployment/staking/polygon/deploy_06_polygon_targer_dispenser.js b/scripts/deployment/staking/polygon/deploy_06_polygon_targer_dispenser.js index 10b7f502..45cbeab6 100644 --- a/scripts/deployment/staking/polygon/deploy_06_polygon_targer_dispenser.js +++ b/scripts/deployment/staking/polygon/deploy_06_polygon_targer_dispenser.js @@ -48,7 +48,7 @@ async function main() { const polygonTargetDispenserL2 = await PolygonTargetDispenserL2.connect(EOA).deploy(parsedData.olasAddress, parsedData.serviceStakingFactoryAddress, parsedData.polygonFXChildAddress, parsedData.polygonDepositProcessorL1Address, parsedData.l1ChainId, { gasPrice }); - const result = await polygonTargetDispenserL2.deployed(); + let result = await polygonTargetDispenserL2.deployed(); // Transaction details console.log("Contract deployment: PolygonTargetDispenserL2"); @@ -62,6 +62,10 @@ async function main() { parsedData.polygonTargetDispenserL2Address = polygonTargetDispenserL2.address; fs.writeFileSync(globalsFile, JSON.stringify(parsedData)); + console.log("You are signing the following transaction: PolygonTargetDispenserL2.connect(EOA).setFxRootTunnel()"); + result = await polygonTargetDispenserL2.setFxRootTunnel(parsedData.polygonDepositProcessorL1Address); + console.log("Transaction:", result.hash); + // Contract verification if (parsedData.contractVerification) { const execSync = require("child_process").execSync; diff --git a/scripts/deployment/staking/polygon/deploy_61_change_owner.js b/scripts/deployment/staking/polygon/deploy_61_change_owner.js new file mode 100644 index 00000000..7a15c82b --- /dev/null +++ b/scripts/deployment/staking/polygon/deploy_61_change_owner.js @@ -0,0 +1,48 @@ +/*global process*/ + +const { ethers } = require("hardhat"); +const { LedgerSigner } = require("@anders-t/ethers-ledger"); + +async function main() { + const fs = require("fs"); + const globalsFile = "globals.json"; + const dataFromJSON = fs.readFileSync(globalsFile, "utf8"); + let parsedData = JSON.parse(dataFromJSON); + const useLedger = parsedData.useLedger; + const derivationPath = parsedData.derivationPath; + const providerName = parsedData.providerName; + const polygonTargetDispenserL2Address = parsedData.polygonTargetDispenserL2Address; + const bridgeMediatorAddress = parsedData.bridgeMediatorAddress; + + let networkURL = parsedData.networkURL; + const provider = new ethers.providers.JsonRpcProvider(networkURL); + const signers = await ethers.getSigners(); + + let EOA; + if (useLedger) { + EOA = new LedgerSigner(provider, derivationPath); + } else { + EOA = signers[0]; + } + // EOA address + const deployer = await EOA.getAddress(); + console.log("EOA is:", deployer); + + // Transaction signing and execution + console.log("61. EOA to change owner in PolygonTargetDispenserL2"); + const polygonTargetDispenserL2 = await ethers.getContractAt("PolygonTargetDispenserL2", polygonTargetDispenserL2Address); + console.log("You are signing the following transaction: PolygonTargetDispenserL2.connect(EOA).changeOwner()"); + const result = await polygonTargetDispenserL2.connect(EOA).changeOwner(bridgeMediatorAddress); + + // Transaction details + console.log("Contract deployment: PolygonTargetDispenserL2"); + console.log("Contract address:", polygonTargetDispenserL2.address); + console.log("Transaction:", result.hash); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/scripts/deployment/staking/polygon/globals_polygon_mainnet.json b/scripts/deployment/staking/polygon/globals_polygon_mainnet.json new file mode 100644 index 00000000..41760b04 --- /dev/null +++ b/scripts/deployment/staking/polygon/globals_polygon_mainnet.json @@ -0,0 +1 @@ +{"contractVerification":true,"useLedger":true,"derivationPath":"m/44'/60'/2'/0/0","providerName":"polygon","networkURL":"https://polygon-mainnet.g.alchemy.com/v2/","gasPriceInGwei":"5","olasAddress":"0xFEF5d947472e72Efbb2E388c730B7428406F2F95","serviceStakingFactoryAddress":"0x46C0D07F55d4F9B5Eed2Fc9680B5953e5fd7b461","bridgeMediatorAddress":"0x9338b5153AE39BB89f50468E608eD9d764B755fD","polygonFXChildAddress":"0x8397259c983751DAf40400790063935a11afa28a","l1ChainId":"1","polygonDepositProcessorL1Address":"0x4Ce43b82EF1298E1466D3b3Cee67BA6680bF82FB","polygonTargetDispenserL2Address":"0xf76953444C35F1FcE2F6CA1b167173357d3F5C17"} \ No newline at end of file diff --git a/scripts/deployment/staking/verify_05_wormhole_deposit_processor.js b/scripts/deployment/staking/verify_05_celo_deposit_processor.js similarity index 100% rename from scripts/deployment/staking/verify_05_wormhole_deposit_processor.js rename to scripts/deployment/staking/verify_05_celo_deposit_processor.js diff --git a/scripts/deployment/staking/verify_07_base_deposit_processor.js b/scripts/deployment/staking/verify_07_base_deposit_processor.js new file mode 100644 index 00000000..c7855344 --- /dev/null +++ b/scripts/deployment/staking/verify_07_base_deposit_processor.js @@ -0,0 +1,13 @@ +const fs = require("fs"); +const globalsFile = "globals.json"; +const dataFromJSON = fs.readFileSync(globalsFile, "utf8"); +const parsedData = JSON.parse(dataFromJSON); + +module.exports = [ + parsedData.olasAddress, + parsedData.dispenserAddress, + parsedData.baseL1StandardBridgeProxyAddress, + parsedData.baseL1CrossDomainMessengerProxyAddress, + parsedData.baseL2TargetChainId, + parsedData.baseOLASAddress +]; \ No newline at end of file diff --git a/scripts/deployment/staking/verify_08_ethereum_deposit_processor.js b/scripts/deployment/staking/verify_08_ethereum_deposit_processor.js new file mode 100644 index 00000000..d1a3c206 --- /dev/null +++ b/scripts/deployment/staking/verify_08_ethereum_deposit_processor.js @@ -0,0 +1,11 @@ +const fs = require("fs"); +const globalsFile = "globals.json"; +const dataFromJSON = fs.readFileSync(globalsFile, "utf8"); +const parsedData = JSON.parse(dataFromJSON); + +module.exports = [ + parsedData.olasAddress, + parsedData.dispenserAddress, + parsedData.serviceStakingFactoryAddress, + parsedData.timelockAddress +]; \ No newline at end of file diff --git a/scripts/deployment/staking/wormhole/bridge_new_token.js b/scripts/deployment/staking/wormhole/test/bridge_new_token.js similarity index 100% rename from scripts/deployment/staking/wormhole/bridge_new_token.js rename to scripts/deployment/staking/wormhole/test/bridge_new_token.js diff --git a/scripts/deployment/staking/wormhole/deploy_00_mock_olas_as_erc20_ownerless.js b/scripts/deployment/staking/wormhole/test/deploy_00_mock_olas_as_erc20_ownerless.js similarity index 100% rename from scripts/deployment/staking/wormhole/deploy_00_mock_olas_as_erc20_ownerless.js rename to scripts/deployment/staking/wormhole/test/deploy_00_mock_olas_as_erc20_ownerless.js diff --git a/scripts/deployment/staking/wormhole/deploy_01_mock_dispenser.js b/scripts/deployment/staking/wormhole/test/deploy_01_mock_dispenser.js similarity index 94% rename from scripts/deployment/staking/wormhole/deploy_01_mock_dispenser.js rename to scripts/deployment/staking/wormhole/test/deploy_01_mock_dispenser.js index a035270c..a7b7d733 100644 --- a/scripts/deployment/staking/wormhole/deploy_01_mock_dispenser.js +++ b/scripts/deployment/staking/wormhole/test/deploy_01_mock_dispenser.js @@ -63,7 +63,7 @@ async function main() { // Contract verification if (parsedData.contractVerification) { const execSync = require("child_process").execSync; - execSync("npx hardhat verify --constructor-args scripts/deployment/staking/wormhole/verify_01_mock_dispenser.js --network " + providerName + " " + dispenser.address, { encoding: "utf-8" }); + execSync("npx hardhat verify --constructor-args scripts/deployment/staking/wormhole/test/verify_01_mock_dispenser.js --network " + providerName + " " + dispenser.address, { encoding: "utf-8" }); } } diff --git a/scripts/deployment/staking/wormhole/deploy_05_celo_wormhole_targer_dispenser.js b/scripts/deployment/staking/wormhole/test/deploy_05_celo_wormhole_targer_dispenser.js similarity index 94% rename from scripts/deployment/staking/wormhole/deploy_05_celo_wormhole_targer_dispenser.js rename to scripts/deployment/staking/wormhole/test/deploy_05_celo_wormhole_targer_dispenser.js index 3bb9c756..342a2bbd 100644 --- a/scripts/deployment/staking/wormhole/deploy_05_celo_wormhole_targer_dispenser.js +++ b/scripts/deployment/staking/wormhole/test/deploy_05_celo_wormhole_targer_dispenser.js @@ -64,7 +64,7 @@ async function main() { // Contract verification if (parsedData.contractVerification) { const execSync = require("child_process").execSync; - execSync("npx hardhat verify --constructor-args scripts/deployment/staking/wormhole/verify_05_celo_wormhole_target_dispenser.js --network " + providerName + " " + wormholeTargetDispenserL2.address, { encoding: "utf-8" }); + execSync("npx hardhat verify --constructor-args scripts/deployment/staking/wormhole/test/verify_05_celo_wormhole_target_dispenser.js --network " + providerName + " " + wormholeTargetDispenserL2.address, { encoding: "utf-8" }); } } diff --git a/scripts/deployment/staking/wormhole/deploy_05_polygon_wormhole_deposit_processor.js b/scripts/deployment/staking/wormhole/test/deploy_05_polygon_wormhole_deposit_processor.js similarity index 94% rename from scripts/deployment/staking/wormhole/deploy_05_polygon_wormhole_deposit_processor.js rename to scripts/deployment/staking/wormhole/test/deploy_05_polygon_wormhole_deposit_processor.js index 3b2cc674..b3f41be9 100644 --- a/scripts/deployment/staking/wormhole/deploy_05_polygon_wormhole_deposit_processor.js +++ b/scripts/deployment/staking/wormhole/test/deploy_05_polygon_wormhole_deposit_processor.js @@ -64,7 +64,7 @@ async function main() { // Contract verification if (parsedData.contractVerification) { const execSync = require("child_process").execSync; - execSync("npx hardhat verify --constructor-args scripts/deployment/staking/wormhole/verify_05_polygon_wormhole_deposit_processor.js --network " + providerName + " " + wormholeDepositProcessorL1.address, { encoding: "utf-8" }); + execSync("npx hardhat verify --constructor-args scripts/deployment/staking/wormhole/test/verify_05_polygon_wormhole_deposit_processor.js --network " + providerName + " " + wormholeDepositProcessorL1.address, { encoding: "utf-8" }); } } diff --git a/scripts/deployment/staking/wormhole/globals_celo_mainnet.json b/scripts/deployment/staking/wormhole/test/globals_celo_mainnet.json similarity index 100% rename from scripts/deployment/staking/wormhole/globals_celo_mainnet.json rename to scripts/deployment/staking/wormhole/test/globals_celo_mainnet.json diff --git a/scripts/deployment/staking/wormhole/globals_polygon_mainnet.json b/scripts/deployment/staking/wormhole/test/globals_polygon_mainnet.json similarity index 100% rename from scripts/deployment/staking/wormhole/globals_polygon_mainnet.json rename to scripts/deployment/staking/wormhole/test/globals_polygon_mainnet.json diff --git a/scripts/deployment/staking/wormhole/send_tokens_and_message.js b/scripts/deployment/staking/wormhole/test/send_tokens_and_message.js similarity index 100% rename from scripts/deployment/staking/wormhole/send_tokens_and_message.js rename to scripts/deployment/staking/wormhole/test/send_tokens_and_message.js diff --git a/scripts/deployment/staking/wormhole/verify_01_mock_dispenser.js b/scripts/deployment/staking/wormhole/test/verify_01_mock_dispenser.js similarity index 100% rename from scripts/deployment/staking/wormhole/verify_01_mock_dispenser.js rename to scripts/deployment/staking/wormhole/test/verify_01_mock_dispenser.js diff --git a/scripts/deployment/staking/wormhole/test/verify_05_celo_wormhole_target_dispenser.js b/scripts/deployment/staking/wormhole/test/verify_05_celo_wormhole_target_dispenser.js new file mode 100644 index 00000000..3028f790 --- /dev/null +++ b/scripts/deployment/staking/wormhole/test/verify_05_celo_wormhole_target_dispenser.js @@ -0,0 +1,14 @@ +const fs = require("fs"); +const globalsFile = "globals.json"; +const dataFromJSON = fs.readFileSync(globalsFile, "utf8"); +const parsedData = JSON.parse(dataFromJSON); + +module.exports = [ + parsedData.olasAddress, + parsedData.serviceStakingFactoryAddress, + parsedData.wormholeL2MessageRelayer, + parsedData.celoWormholeDepositProcessorL1Address, + parsedData.wormholel1ChainId, + parsedData.wormholeL2CoreAddress, + parsedData.wormholeL2TokenRelayerAddress +]; \ No newline at end of file diff --git a/scripts/deployment/staking/wormhole/verify_05_polygon_wormhole_deposit_processor.js b/scripts/deployment/staking/wormhole/test/verify_05_polygon_wormhole_deposit_processor.js similarity index 100% rename from scripts/deployment/staking/wormhole/verify_05_polygon_wormhole_deposit_processor.js rename to scripts/deployment/staking/wormhole/test/verify_05_polygon_wormhole_deposit_processor.js diff --git a/scripts/deployment/verify_07_dispenser.js b/scripts/deployment/verify_07_dispenser.js index f8cc6de3..b5cdd7e7 100644 --- a/scripts/deployment/verify_07_dispenser.js +++ b/scripts/deployment/verify_07_dispenser.js @@ -4,8 +4,22 @@ const dataFromJSON = fs.readFileSync(globalsFile, "utf8"); const parsedData = JSON.parse(dataFromJSON); const tokenomicsProxyAddress = parsedData.tokenomicsProxyAddress; const treasuryAddress = parsedData.treasuryAddress; +const olasAddress = parsedData.olasAddress; +const voteWeightingAddress = parsedData.voteWeightingAddress; +const retainerAddress = parsedData.retainerAddress; +const maxNumClaimingEpochs = parsedData.maxNumClaimingEpochs; +const maxNumStakingTargets = parsedData.maxNumStakingTargets; +const minStakingWeight = parsedData.minStakingWeight; +const maxStakingIncentive = parsedData.maxStakingIncentive; module.exports = [ + olasAddress, tokenomicsProxyAddress, - treasuryAddress + treasuryAddress, + voteWeightingAddress, + retainerAddress, + maxNumClaimingEpochs, + maxNumStakingTargets, + minStakingWeight, + maxStakingIncentive ]; \ No newline at end of file diff --git a/scripts/proposals/proposal_09_change_dispenser_and_disable_previous_one.js b/scripts/proposals/proposal_09_change_dispenser_and_disable_previous_one.js new file mode 100644 index 00000000..f3a93114 --- /dev/null +++ b/scripts/proposals/proposal_09_change_dispenser_and_disable_previous_one.js @@ -0,0 +1,69 @@ +/*global process*/ + +const { ethers } = require("hardhat"); + +async function main() { + const fs = require("fs"); + const globalsFile = "globals.json"; + const dataFromJSON = fs.readFileSync(globalsFile, "utf8"); + let parsedData = JSON.parse(dataFromJSON); + const providerName = parsedData.providerName; + + const provider = await ethers.providers.getDefaultProvider(providerName); + + // Get all the necessary contract addresses + const tokenomicsProxyAddress = parsedData.tokenomicsProxyAddress; + const treasuryAddress = parsedData.treasuryAddress; + const dispenserAddress = parsedData.dispenserAddress; + const arbitrumDepositProcessorL1Address = parsedData.arbitrumDepositProcessorL1Address; + const baseDepositProcessorL1Address = parsedData.baseDepositProcessorL1Address; + const celoDepositProcessorL1Address = parsedData.celoDepositProcessorL1Address; + const ethereumDepositProcessorAddress = parsedData.ethereumDepositProcessorAddress; + const gnosisDepositProcessorL1Address = parsedData.gnosisDepositProcessorL1Address; + const optimismDepositProcessorL1Address = parsedData.optimismDepositProcessorL1Address; + const polygonDepositProcessorL1Address = parsedData.polygonDepositProcessorL1Address; + const minStakingWeight = parsedData.minStakingWeight; + const maxStakingIncentive = parsedData.maxStakingIncentive; + + // Get contract instances + const tokenomics = await ethers.getContractAt("Tokenomics", tokenomicsProxyAddress); + const treasury = await ethers.getContractAt("Treasury", treasuryAddress); + + const oldDispenserAddress = "0xeED0000fE94d7cfeF4Dc0CA86a223f0F603A61B8"; + const dispenserJSON = "abis/0.8.18/Dispenser.json"; + const contractFromJSON = fs.readFileSync(dispenserJSON, "utf8"); + const parsedFile = JSON.parse(contractFromJSON); + const abi = parsedFile["abi"]; + const oldDispenser = new ethers.Contract(oldDispenserAddress, abi, provider); + + const AddressZero = ethers.constants.AddressZero; + const AddressNull = "0x000000000000000000000000000000000000dEaD"; + + // Proposal preparation + console.log("Proposal 9. Change dispenser address in tokenomics and treasury, disable old Dispenser"); + const targets = [tokenomicsProxyAddress, tokenomicsProxyAddress, treasuryAddress, oldDispenserAddress, + oldDispenserAddress]; + const values = [0, 0, 0, 0, 0]; + const callDatas = [ + tokenomics.interface.encodeFunctionData("changeManagers", [AddressZero, AddressZero, dispenserAddress]), + tokenomics.interface.encodeFunctionData("changeStakingParams", [maxStakingIncentive, minStakingWeight]), + treasury.interface.encodeFunctionData("changeManagers", [AddressZero, AddressZero, dispenserAddress]), + oldDispenser.interface.encodeFunctionData("changeManagers", [AddressNull, AddressNull]), + oldDispenser.interface.encodeFunctionData("changeOwner", [AddressNull]) + ]; + + const description = "Change Dispenser address in Tokenomics and Treasury, disable old Dispenser"; + + // Proposal details + console.log("targets:", targets); + console.log("values:", values); + console.log("call datas:", callDatas); + console.log("description:", description); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/test/Depository.t.sol b/test/Depository.t.sol index 0036156a..4971f5b2 100644 --- a/test/Depository.t.sol +++ b/test/Depository.t.sol @@ -6,8 +6,9 @@ import {ZuniswapV2Factory} from "zuniswapv2/ZuniswapV2Factory.sol"; import {ZuniswapV2Router} from "zuniswapv2/ZuniswapV2Router.sol"; import {ZuniswapV2Pair} from "zuniswapv2/ZuniswapV2Pair.sol"; import {Depository} from "../contracts/Depository.sol"; -import {GenericBondCalculator} from "../contracts/GenericBondCalculator.sol"; +import {BondCalculator, DiscountParams} from "../contracts/BondCalculator.sol"; import {MockTokenomics} from "../contracts/test/MockTokenomics.sol"; +import {MockVE} from "../contracts/test/MockVE.sol"; import {Treasury} from "../contracts/Treasury.sol"; import {MockERC20} from "../lib/zuniswapv2/lib/solmate/src/test/utils/mocks/MockERC20.sol"; @@ -20,7 +21,8 @@ contract BaseSetup is Test { MockTokenomics internal tokenomics; Treasury internal treasury; Depository internal depository; - GenericBondCalculator internal genericBondCalculator; + BondCalculator internal bondCalculator; + MockVE internal ve; address payable[] internal users; address internal deployer; @@ -56,11 +58,16 @@ contract BaseSetup is Test { tokenomics = new MockTokenomics(); // Correct depository address is missing here, it will be defined just one line below treasury = new Treasury(address(olas), address(tokenomics), deployer, deployer); - // Deploy generic bond calculator contract - genericBondCalculator = new GenericBondCalculator(address(olas), address(tokenomics)); + // veOLAS + ve = new MockVE(); + // Deploy bond calculator contract + DiscountParams memory discountParams; + discountParams.targetVotingPower = 10 ether; + discountParams.targetNewUnits = 10; + bondCalculator = new BondCalculator(address(olas), address(tokenomics), address(ve), discountParams); // Deploy depository contract depository = new Depository("Depository", "OLAS_BOND", "baseURI", address(olas), address(tokenomics), - address(treasury), address(genericBondCalculator)); + address(treasury), address(bondCalculator)); // Change depository contract addresses to the correct ones treasury.changeManagers(address(0), address(depository), address(0)); diff --git a/test/Depository2BondCalculator.js b/test/Depository2BondCalculator.js index 37004f6c..6c49513d 100644 --- a/test/Depository2BondCalculator.js +++ b/test/Depository2BondCalculator.js @@ -264,6 +264,10 @@ describe("Depository LP 2 Bond Calculator", async () => { defaultDiscountParams.weightFactors[3] = 1000; // Now able to change discount params await bondCalculator.changeDiscountParams(defaultDiscountParams); + + + const checkDiscountParams = await bondCalculator.getDiscountParams(); + expect(checkDiscountParams.weightFactors[3]).to.equal(defaultDiscountParams.weightFactors[3]); }); }); diff --git a/test/Depository2GenericBondCalculator.js b/test/Depository2GenericBondCalculator.js index 1f0ae270..91f14ce4 100644 --- a/test/Depository2GenericBondCalculator.js +++ b/test/Depository2GenericBondCalculator.js @@ -18,7 +18,7 @@ describe("Depository LP 2 Generic Bond Calculator", async () => { let olasFactory; let depositoryFactory; let tokenomicsFactory; - let genericBondCalculator; + let bondCalculator; let router; let factory; @@ -29,6 +29,7 @@ describe("Depository LP 2 Generic Bond Calculator", async () => { let treasury; let treasuryFactory; let tokenomics; + let ve; let epochLen = 86400 * 10; let defaultPriceLP = "2" + decimals; @@ -40,10 +41,16 @@ describe("Depository LP 2 Generic Bond Calculator", async () => { let vesting = oneWeek; - var productId = 0; + let productId = 0; let first; let id; + const discountParams = { + targetVotingPower: ethers.utils.parseEther("10"), + targetNewUnits: 10, + weightFactors: new Array(4).fill(0) + }; + let attackDepositFactory; let attackDeposit; @@ -64,22 +71,28 @@ describe("Depository LP 2 Generic Bond Calculator", async () => { dai = await erc20Token.deploy(); olas = await olasFactory.deploy(); + + // Voting Escrow mock + const VE = await ethers.getContractFactory("MockVE"); + ve = await VE.deploy(); + await ve.deployed(); + // Correct treasury address is missing here, it will be defined just one line below tokenomics = await tokenomicsFactory.deploy(); await tokenomics.initializeTokenomics(olas.address, deployer.address, deployer.address, deployer.address, - deployer.address, epochLen, deployer.address, deployer.address, deployer.address, AddressZero); + ve.address, epochLen, deployer.address, deployer.address, deployer.address, AddressZero); // Correct depository address is missing here, it will be defined just one line below treasury = await treasuryFactory.deploy(olas.address, tokenomics.address, deployer.address, deployer.address); // Change bond fraction to 100% in these tests await tokenomics.changeIncentiveFractions(66, 34, 100, 0, 0, 0); // Deploy generic bond calculator contract - const GenericBondCalculator = await ethers.getContractFactory("GenericBondCalculator"); - genericBondCalculator = await GenericBondCalculator.deploy(olas.address, tokenomics.address); - await genericBondCalculator.deployed(); + const BondCalculator = await ethers.getContractFactory("BondCalculator"); + bondCalculator = await BondCalculator.deploy(olas.address, tokenomics.address, ve.address, discountParams); + await bondCalculator.deployed(); // Deploy depository contract depository = await depositoryFactory.deploy("Depository", "OLAS_BOND", baseURI, olas.address, - tokenomics.address, treasury.address, genericBondCalculator.address); + tokenomics.address, treasury.address, bondCalculator.address); // Deploy Attack example attackDeposit = await attackDepositFactory.deploy(); @@ -220,7 +233,7 @@ describe("Depository LP 2 Generic Bond Calculator", async () => { // Trying to change bond calculator to a zero address that results in no change await depository.connect(deployer).changeBondCalculator(AddressZero); - expect(await depository.bondCalculator()).to.equal(genericBondCalculator.address); + expect(await depository.bondCalculator()).to.equal(bondCalculator.address); // Change bond calculator address await depository.connect(deployer).changeBondCalculator(account.address); diff --git a/test/DepositoryGenericBondCalculator.js b/test/DepositoryGenericBondCalculator.js index 22082e6a..666ac7d2 100644 --- a/test/DepositoryGenericBondCalculator.js +++ b/test/DepositoryGenericBondCalculator.js @@ -18,7 +18,7 @@ describe("Depository LP Generic Bond Calculator", async () => { let olasFactory; let depositoryFactory; let tokenomicsFactory; - let genericBondCalculator; + let bondCalculator; let router; let factory; @@ -29,6 +29,7 @@ describe("Depository LP Generic Bond Calculator", async () => { let treasury; let treasuryFactory; let tokenomics; + let ve; let epochLen = 86400 * 10; let defaultPriceLP = "2" + decimals; @@ -45,6 +46,12 @@ describe("Depository LP Generic Bond Calculator", async () => { let first; let id; + const discountParams = { + targetVotingPower: ethers.utils.parseEther("10"), + targetNewUnits: 10, + weightFactors: new Array(4).fill(0) + }; + let attackDepositFactory; let attackDeposit; @@ -65,22 +72,28 @@ describe("Depository LP Generic Bond Calculator", async () => { dai = await erc20Token.deploy(); olas = await olasFactory.deploy(); + + // Voting Escrow mock + const VE = await ethers.getContractFactory("MockVE"); + ve = await VE.deploy(); + await ve.deployed(); + // Correct treasury address is missing here, it will be defined just one line below tokenomics = await tokenomicsFactory.deploy(); await tokenomics.initializeTokenomics(olas.address, deployer.address, deployer.address, deployer.address, - deployer.address, epochLen, deployer.address, deployer.address, deployer.address, AddressZero); + ve.address, epochLen, deployer.address, deployer.address, deployer.address, AddressZero); // Correct depository address is missing here, it will be defined just one line below treasury = await treasuryFactory.deploy(olas.address, tokenomics.address, deployer.address, deployer.address); // Change bond fraction to 100% in these tests await tokenomics.changeIncentiveFractions(66, 34, 100, 0, 0, 0); // Deploy generic bond calculator contract - const GenericBondCalculator = await ethers.getContractFactory("GenericBondCalculator"); - genericBondCalculator = await GenericBondCalculator.deploy(olas.address, tokenomics.address); - await genericBondCalculator.deployed(); + const BondCalculator = await ethers.getContractFactory("BondCalculator"); + bondCalculator = await BondCalculator.deploy(olas.address, tokenomics.address, ve.address, discountParams); + await bondCalculator.deployed(); // Deploy depository contract depository = await depositoryFactory.deploy("Depository", "OLAS_BOND", baseURI, olas.address, - tokenomics.address, treasury.address, genericBondCalculator.address); + tokenomics.address, treasury.address, bondCalculator.address); // Deploy Attack example attackDeposit = await attackDepositFactory.deploy(); @@ -242,7 +255,7 @@ describe("Depository LP Generic Bond Calculator", async () => { // Trying to change bond calculator to a zero address that results in no change await depository.connect(deployer).changeBondCalculator(AddressZero); - expect(await depository.bondCalculator()).to.equal(genericBondCalculator.address); + expect(await depository.bondCalculator()).to.equal(bondCalculator.address); // Change bond calculator address await depository.connect(deployer).changeBondCalculator(account.address); @@ -250,13 +263,13 @@ describe("Depository LP Generic Bond Calculator", async () => { }); it("Should fail if any of bond calculator input addresses is a zero address", async function () { - const GenericBondCalculator = await ethers.getContractFactory("GenericBondCalculator"); + const BondCalculator = await ethers.getContractFactory("BondCalculator"); await expect( - GenericBondCalculator.deploy(AddressZero, tokenomics.address) - ).to.be.revertedWithCustomError(genericBondCalculator, "ZeroAddress"); + BondCalculator.deploy(AddressZero, tokenomics.address, AddressZero, discountParams) + ).to.be.revertedWithCustomError(bondCalculator, "ZeroAddress"); await expect( - GenericBondCalculator.deploy(olas.address, AddressZero) - ).to.be.revertedWithCustomError(genericBondCalculator, "ZeroAddress"); + BondCalculator.deploy(olas.address, AddressZero, AddressZero, discountParams) + ).to.be.revertedWithCustomError(bondCalculator, "ZeroAddress"); }); }); @@ -920,7 +933,7 @@ describe("Depository LP Generic Bond Calculator", async () => { // Now change the depository contract address const newDepository = await depositoryFactory.deploy("Depository", "OLAS_BOND", baseURI, olas.address, - tokenomics.address, treasury.address, genericBondCalculator.address); + tokenomics.address, treasury.address, bondCalculator.address); // Change to a new depository address await treasury.changeManagers(AddressZero, newDepository.address, AddressZero); diff --git a/test/Dispenser.t.sol b/test/Dispenser.t.sol index d9a12bfb..da8c5918 100644 --- a/test/Dispenser.t.sol +++ b/test/Dispenser.t.sol @@ -33,6 +33,7 @@ contract BaseSetup is Test { uint256 internal initialMint = 10_000_000_000e18; uint256 internal largeApproval = 1_000_000_000_000e18; uint256 epochLen = 30 days; + uint256 delta = 100; function setUp() public virtual { emptyArray = new uint256[](0); @@ -106,8 +107,8 @@ contract DispenserTest is BaseSetup { assertEq(reward, 0); assertEq(topUp, 0); - // Lock OLAS balances with Voting Escrow - ve.setWeightedBalance(tokenomics.veOLASThreshold()); + // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation + ve.setWeightedBalance(tokenomics.inflationPerSecond() * 365 days); ve.createLock(deployer); // Change the first service owner to the deployer (same for components and agents) @@ -173,20 +174,20 @@ contract DispenserTest is BaseSetup { balanceETH = address(deployer).balance - balanceETH; balanceOLAS = olas.balanceOf(deployer) - balanceOLAS; assertEq(balanceETH, accountRewards); - assertEq(balanceOLAS, accountTopUps); + assertLt(accountTopUps - balanceOLAS, delta); } /// @dev Deposit incentives for 2 services in a loop to go through a specified amount of time. /// @notice Assume that no single donation is bigger than 2^64 - 1. /// @param amount0 Amount to donate to the first service. /// @param amount1 Amount to donate to the second service. - function testIncentivesLoopDirect(uint64 amount0, uint64 amount1) public { + function testLoopDirectIncentives(uint64 amount0, uint64 amount1) public { // Amounts must be meaningful vm.assume(amount0 > treasury.minAcceptedETH()); vm.assume(amount1 > treasury.minAcceptedETH()); - // Lock OLAS balances with Voting Escrow - ve.setWeightedBalance(tokenomics.veOLASThreshold()); + // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation + ve.setWeightedBalance(tokenomics.getInflationForYear(4)); ve.createLock(deployer); // Change the first service owner to the deployer (same for components and agents) @@ -264,7 +265,7 @@ contract DispenserTest is BaseSetup { balanceETH = address(deployer).balance - balanceETH; balanceOLAS = olas.balanceOf(deployer) - balanceOLAS; assertEq(balanceETH, accountRewards); - assertEq(balanceOLAS, accountTopUps); + assertLt(accountTopUps - balanceOLAS, delta); } } @@ -277,8 +278,8 @@ contract DispenserTest is BaseSetup { vm.assume(amount0 > treasury.minAcceptedETH()); vm.assume(amount1 > treasury.minAcceptedETH()); - // Lock OLAS balances with Voting Escrow - ve.setWeightedBalance(tokenomics.veOLASThreshold()); + // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation + ve.setWeightedBalance(tokenomics.getInflationForYear(4)); ve.createLock(deployer); // Change the first service owner to the deployer (same for components and agents) @@ -341,7 +342,7 @@ contract DispenserTest is BaseSetup { balanceETH = address(deployer).balance - balanceETH; balanceOLAS = olas.balanceOf(deployer) - balanceOLAS; assertEq(balanceETH, accountRewards); - assertEq(balanceOLAS, accountTopUps); + assertLt(accountTopUps - balanceOLAS, delta); // Zero previously calculated rewards and top-ups rewards[0] = 0; diff --git a/test/DispenserDevIncentives.js b/test/DispenserDevIncentives.js index fecbf5f0..e3a20d79 100644 --- a/test/DispenserDevIncentives.js +++ b/test/DispenserDevIncentives.js @@ -225,12 +225,11 @@ describe("DispenserDevIncentives", async () => { await helpers.time.increase(epochLen + 10); await tokenomics.connect(deployer).checkpoint(); - // Get tokenomcis parameters from the previous epoch + // Get tokenomics parameters from the previous epoch let lastPoint = Number(await tokenomics.epochCounter()) - 1; // Get the epoch point of the last epoch let ep = await tokenomics.mapEpochTokenomics(lastPoint); expect(await tokenomics.devsPerCapital()).to.greaterThan(0); - expect(ep.idf).to.greaterThan(0); // Get the unit points of the last epoch let up = [await tokenomics.getUnitPoint(lastPoint, 0), await tokenomics.getUnitPoint(lastPoint, 1)]; expect(up[0].rewardUnitFraction + up[1].rewardUnitFraction + ep.rewardTreasuryFraction).to.equal(100); @@ -260,6 +259,121 @@ describe("DispenserDevIncentives", async () => { // Start new epoch and calculate tokenomics parameters and rewards await tokenomics.connect(deployer).checkpoint(); + // Get the last settled epoch counter + lastPoint = Number(await tokenomics.epochCounter()) - 1; + // Get the epoch point of the last epoch + ep = await tokenomics.mapEpochTokenomics(lastPoint); + // Get the unit points of the last epoch + up = [await tokenomics.getUnitPoint(lastPoint, 0), await tokenomics.getUnitPoint(lastPoint, 1)]; + // Calculate rewards based on the points information + const percentFraction = ethers.BigNumber.from(100); + let rewards = [ + ethers.BigNumber.from(ep.totalDonationsETH).mul(ethers.BigNumber.from(up[0].rewardUnitFraction)).div(percentFraction), + ethers.BigNumber.from(ep.totalDonationsETH).mul(ethers.BigNumber.from(up[1].rewardUnitFraction)).div(percentFraction) + ]; + let accountRewards = rewards[0].add(rewards[1]); + expect(accountRewards).to.greaterThan(0); + + // Since minWeightedBalance < top-ups inflation per epoch, the max top-ups can be equal to minWeightedBalance + let accountTopUps = minWeightedBalance; + expect(accountTopUps).to.greaterThan(0); + + // Check for the incentive balances of component and agent such that their pending relative incentives are non-zero + let incentiveBalances = await tokenomics.mapUnitIncentives(0, 1); + expect(Number(incentiveBalances.pendingRelativeReward)).to.greaterThan(0); + expect(Number(incentiveBalances.pendingRelativeTopUp)).to.greaterThan(0); + incentiveBalances = await tokenomics.mapUnitIncentives(1, 1); + expect(incentiveBalances.pendingRelativeReward).to.greaterThan(0); + expect(incentiveBalances.pendingRelativeTopUp).to.greaterThan(0); + + // Get deployer incentives information + const result = await tokenomics.getOwnerIncentives(deployer.address, [0, 1], [1, 1]); + // Get accumulated rewards and top-ups + const checkedReward = ethers.BigNumber.from(result.reward); + const checkedTopUp = ethers.BigNumber.from(result.topUp); + // Check if they match with what was written to the tokenomics point with owner reward and top-up fractions + // Theoretical values must always be bigger than calculated ones (since round-off error is due to flooring) + expect(Math.abs(Number(accountRewards.sub(checkedReward)))).to.lessThan(delta); + expect(Math.abs(Number(accountTopUps.sub(checkedTopUp)))).to.lessThan(delta); + + // Simulate claiming rewards and top-ups for owners and check their correctness + const claimedOwnerIncentives = await dispenser.connect(deployer).callStatic.claimOwnerIncentives([0, 1], [1, 1]); + // Get accumulated rewards and top-ups + let claimedReward = ethers.BigNumber.from(claimedOwnerIncentives.reward); + let claimedTopUp = ethers.BigNumber.from(claimedOwnerIncentives.topUp); + + // Check if they match with what was written to the tokenomics point with owner reward and top-up fractions + expect(claimedReward).to.lessThanOrEqual(accountRewards); + expect(Math.abs(Number(accountRewards.sub(claimedReward)))).to.lessThan(delta); + expect(claimedTopUp).to.lessThanOrEqual(accountTopUps); + expect(Math.abs(Number(accountTopUps.sub(claimedTopUp)))).to.lessThan(delta); + + // Claim rewards and top-ups + const balanceBeforeTopUps = ethers.BigNumber.from(await olas.balanceOf(deployer.address)); + await dispenser.connect(deployer).claimOwnerIncentives([0, 1], [1, 1]); + const balanceAfterTopUps = ethers.BigNumber.from(await olas.balanceOf(deployer.address)); + + // Check the OLAS balance after receiving incentives + const balance = balanceAfterTopUps.sub(balanceBeforeTopUps); + expect(balance).to.lessThanOrEqual(accountTopUps); + expect(Math.abs(Number(accountTopUps.sub(balance)))).to.lessThan(delta); + + // Restore to the state of the snapshot + await snapshot.restore(); + }); + + it("Claim incentives for unit owners with donation voting power bigger than the inflation", async () => { + // Take a snapshot of the current state of the blockchain + const snapshot = await helpers.takeSnapshot(); + + // Try to claim empty incentives + await expect( + dispenser.connect(deployer).claimOwnerIncentives([], []) + ).to.be.revertedWithCustomError(dispenser, "ClaimIncentivesFailed"); + + // Try to claim incentives for non-existent components + await expect( + dispenser.connect(deployer).claimOwnerIncentives([0], [0]) + ).to.be.revertedWithCustomError(tokenomics, "WrongUnitId"); + + // Skip the number of seconds for 2 epochs + await helpers.time.increase(epochLen + 10); + await tokenomics.connect(deployer).checkpoint(); + + // Get tokenomics parameters from the previous epoch + let lastPoint = Number(await tokenomics.epochCounter()) - 1; + // Get the epoch point of the last epoch + let ep = await tokenomics.mapEpochTokenomics(lastPoint); + expect(await tokenomics.devsPerCapital()).to.greaterThan(0); + // Get the unit points of the last epoch + let up = [await tokenomics.getUnitPoint(lastPoint, 0), await tokenomics.getUnitPoint(lastPoint, 1)]; + expect(up[0].rewardUnitFraction + up[1].rewardUnitFraction + ep.rewardTreasuryFraction).to.equal(100); + + await helpers.time.increase(epochLen + 10); + await tokenomics.connect(deployer).checkpoint(); + + // Send ETH to treasury + const amount = ethers.utils.parseEther("1000"); + await deployer.sendTransaction({to: treasury.address, value: amount}); + + // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation + const inflationPerYear = await tokenomics.getInflationForYear(0); + await ve.setWeightedBalance(inflationPerYear.toString()); + await ve.createLock(deployer.address); + + // Change the first service owner to the deployer (same for components and agents) + await serviceRegistry.changeUnitOwner(1, deployer.address); + await componentRegistry.changeUnitOwner(1, deployer.address); + await agentRegistry.changeUnitOwner(1, deployer.address); + + // Send donations to services + await treasury.connect(deployer).depositServiceDonationsETH([1, 2], [regDepositFromServices, regDepositFromServices], + {value: twoRegDepositFromServices}); + // Move more than one epoch in time + await helpers.time.increase(epochLen + 10); + // Start new epoch and calculate tokenomics parameters and rewards + await tokenomics.connect(deployer).checkpoint(); + // Get the last settled epoch counter lastPoint = Number(await tokenomics.epochCounter()) - 1; // Get the epoch point of the last epoch @@ -344,12 +458,11 @@ describe("DispenserDevIncentives", async () => { await helpers.time.increase(epochLen + 10); await tokenomics.connect(deployer).checkpoint(); - // Get tokenomcis parameters from the previous epoch + // Get tokenomics parameters from the previous epoch let lastPoint = Number(await tokenomics.epochCounter()) - 1; // Get the epoch point of the last epoch let ep = await tokenomics.mapEpochTokenomics(lastPoint); expect(await tokenomics.devsPerCapital()).to.greaterThan(0); - expect(ep.idf).to.greaterThan(0); // Get the unit points of the last epoch let up = [await tokenomics.getUnitPoint(lastPoint, 0), await tokenomics.getUnitPoint(lastPoint, 1)]; expect(up[0].rewardUnitFraction + up[1].rewardUnitFraction + ep.rewardTreasuryFraction).to.equal(100); @@ -361,9 +474,9 @@ describe("DispenserDevIncentives", async () => { const amount = ethers.utils.parseEther("1000"); await deployer.sendTransaction({to: treasury.address, value: amount}); - // Lock OLAS balances with Voting Escrow - const minWeightedBalance = await tokenomics.veOLASThreshold(); - await ve.setWeightedBalance(minWeightedBalance.toString()); + // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation + const inflationPerYear = await tokenomics.getInflationForYear(0); + await ve.setWeightedBalance(inflationPerYear.toString()); await ve.createLock(signers[1].address); // Change the first service owner to the deployer (same for components and agents) @@ -508,9 +621,10 @@ describe("DispenserDevIncentives", async () => { expect(checkedTopUp).to.equal(0); // EPOCH 2 with donations and top-ups - // Return the ability for the service owner to have enough veOLAS for the owner top-ups - const minWeightedBalance = await tokenomics.veOLASThreshold(); - await ve.setWeightedBalance(minWeightedBalance.toString()); + // Return the ability to donate + // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation + const inflationPerYear = await tokenomics.getInflationForYear(0); + await ve.setWeightedBalance(inflationPerYear.toString()); await ve.createLock(deployer.address); // Increase the time to more than the length of the epoch @@ -592,9 +706,9 @@ describe("DispenserDevIncentives", async () => { await helpers.time.increase(epochLen + 10); await tokenomics.connect(deployer).checkpoint(); - // Lock OLAS balances with Voting Escrow - const minWeightedBalance = await tokenomics.veOLASThreshold(); - await ve.setWeightedBalance(minWeightedBalance.toString()); + // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation + const inflationPerYear = await tokenomics.getInflationForYear(0); + await ve.setWeightedBalance(inflationPerYear.toString()); await ve.createLock(deployer.address); let totalAccountTopUps = ethers.BigNumber.from(0); @@ -668,9 +782,9 @@ describe("DispenserDevIncentives", async () => { const amount = ethers.utils.parseEther("1000"); await deployer.sendTransaction({to: treasury.address, value: amount}); - // Lock OLAS balances with Voting Escrow - const minWeightedBalance = await tokenomics.veOLASThreshold(); - await ve.setWeightedBalance(minWeightedBalance.toString()); + // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation + const inflationPerYear = await tokenomics.getInflationForYear(0); + await ve.setWeightedBalance(inflationPerYear.toString()); await ve.createLock(deployer.address); // Change the first service owner to the deployer (same for components and agents) @@ -767,9 +881,9 @@ describe("DispenserDevIncentives", async () => { const amount = ethers.utils.parseEther("1000"); await deployer.sendTransaction({to: treasury.address, value: amount}); - // Lock OLAS balances with Voting Escrow - const minWeightedBalance = await tokenomics.veOLASThreshold(); - await ve.setWeightedBalance(minWeightedBalance.toString()); + // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation + const inflationPerYear = await tokenomics.getInflationForYear(0); + await ve.setWeightedBalance(inflationPerYear.toString()); await ve.createLock(deployer.address); // Change the first service owner to the deployer (same for components and agents) @@ -866,9 +980,9 @@ describe("DispenserDevIncentives", async () => { const amount = ethers.utils.parseEther("1000"); await deployer.sendTransaction({to: treasury.address, value: amount}); - // Lock OLAS balances with Voting Escrow - const minWeightedBalance = await tokenomics.veOLASThreshold(); - await ve.setWeightedBalance(minWeightedBalance.toString()); + // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation + const inflationPerYear = await tokenomics.getInflationForYear(0); + await ve.setWeightedBalance(inflationPerYear.toString()); await ve.createLock(deployer.address); // Change the first service owner to the deployer (same for components and agents) @@ -965,9 +1079,9 @@ describe("DispenserDevIncentives", async () => { const amount = ethers.utils.parseEther("1000"); await deployer.sendTransaction({to: treasury.address, value: amount}); - // Lock OLAS balances with Voting Escrow - const minWeightedBalance = await tokenomics.veOLASThreshold(); - await ve.setWeightedBalance(minWeightedBalance.toString()); + // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation + const inflationPerYear = await tokenomics.getInflationForYear(0); + await ve.setWeightedBalance(inflationPerYear.toString()); await ve.createLock(deployer.address); // Change the first service owner to the deployer (same for components and agents) @@ -1083,9 +1197,9 @@ describe("DispenserDevIncentives", async () => { const amount = ethers.utils.parseEther("1000"); await deployer.sendTransaction({to: treasury.address, value: amount}); - // Lock OLAS balances with Voting Escrow - const minWeightedBalance = await tokenomics.veOLASThreshold(); - await ve.setWeightedBalance(minWeightedBalance.toString()); + // Lock OLAS balances with Voting Escrow for a bigger amount compared with top-ups inflation + const inflationPerYear = await tokenomics.getInflationForYear(0); + await ve.setWeightedBalance(inflationPerYear.toString()); await ve.createLock(deployer.address); // Change the first service owner to the deployer (same for components and agents) @@ -1165,7 +1279,12 @@ describe("DispenserDevIncentives", async () => { const amount = ethers.utils.parseEther("1000"); await deployer.sendTransaction({to: treasury.address, value: amount}); - // Lock OLAS balances with Voting Escrow for the attacker + // Unset attack mode in order to receive initial funds + await attacker.setAttackMode(false); + await deployer.sendTransaction({to: attacker.address, value: amount}); + await attacker.setAttackMode(true); + + // Lock OLAS balances for attacker await ve.createLock(attacker.address); // Change the first service owner to the attacker (same for components and agents) @@ -1174,7 +1293,7 @@ describe("DispenserDevIncentives", async () => { await agentRegistry.changeUnitOwner(1, attacker.address); // Send donations to services - await treasury.connect(deployer).depositServiceDonationsETH([1, 2], [regDepositFromServices, regDepositFromServices], + await attacker.depositServiceDonationsETH([1, 2], [regDepositFromServices, regDepositFromServices], {value: twoRegDepositFromServices}); // Move more than one epoch in time await helpers.time.increase(epochLen + 10); diff --git a/test/Tokenomics.js b/test/Tokenomics.js index c95b6134..3f27433b 100644 --- a/test/Tokenomics.js +++ b/test/Tokenomics.js @@ -1020,7 +1020,7 @@ describe("Tokenomics", async () => { await snapshot.restore(); }); - it("Get to the epoch before the end of the OLAS year and try to change maxBond or epochLen", async () => { + it("Get to two epochs before the end of the OLAS year and try to change epochLen", async () => { // Take a snapshot of the current state of the blockchain const snapshot = await helpers.takeSnapshot(); @@ -1030,7 +1030,7 @@ describe("Tokenomics", async () => { const yearChangeTime = timeLaunch + oneYear; // Get to the time of more than one epoch length before the year change (1.5 epoch length) - let timeEpochBeforeYearChange = yearChangeTime - epochLen - epochLen / 2; + const timeEpochBeforeYearChange = yearChangeTime - epochLen - epochLen / 2; await helpers.time.increaseTo(timeEpochBeforeYearChange); await tokenomics.checkpoint(); @@ -1041,12 +1041,23 @@ describe("Tokenomics", async () => { await helpers.time.increase(epochLen); await tokenomics.checkpoint(); expect(await tokenomics.epochLen()).to.equal(2 * epochLen); - // Restore the state of the blockchain back to the time half of the epoch before one epoch left for the current year - snapshotInternal.restore(); + + // Restore to the state of the snapshot + await snapshot.restore(); + }); + + it("Get to the epoch before the end of the OLAS year and try to change epochLen", async () => { + // Take a snapshot of the current state of the blockchain + const snapshot = await helpers.takeSnapshot(); + + // OLAS starting time + const timeLaunch = Number(await tokenomics.timeLaunch()); + // One year time from the launch + const yearChangeTime = timeLaunch + oneYear; // Get to the time of the half epoch length before the year change // Meaning that the year does not change yet during the current epoch, but it will during the next one - timeEpochBeforeYearChange += epochLen; + const timeEpochBeforeYearChange = yearChangeTime - epochLen / 2; await helpers.time.increaseTo(timeEpochBeforeYearChange); await tokenomics.checkpoint();