Address Contract Verified
Address
0x835b1C24462B6A8D433ce1f8B3e22bbcE5682F8b
Balance
0 ETH
Nonce
2
Code Size
16019 bytes
Creator
0x0a8fA62F...19B0 at tx 0x3e972199...aefdee
Indexed Transactions
0
Contract Bytecode
16019 bytes
0x60806040526004361061021d575f3560e01c806380ae2e5c1161011d57806380ae2e5c1461059b5780638d8f3730146105ce57806398ae1f52146105e35780639c823f37146106165780639f08e497146106355780639fc4973414610654578063a6c3ef8b14610682578063b5ed298a146106a1578063bc25cf77146106c0578063c8a7caac146106df578063caf44bd6146106fe578063d3573a331461071d578063d5ca79701461073c578063d64c34fc14610751578063d682e30a14610765578063d850e31914610779578063df61427e14610798578063e3b9bac8146107b7578063e5e933d3146107d6578063ee97f7f3146107ea578063f2bf69f614610808578063f61c266b14610834578063fcbc1d6014610848575f80fd5b8062445e4b14610268578063019dbb631461028957806304b473bd146102be57806310d2b492146102dd578063170c95b71461030957806317f8abb014610349578063241d8afe146103685780633684a72b1461039c5780633f6f34de146103bb5780633f828600146103e8578063438e55a0146104075780634e71e0c8146104265780635c388ca61461043a5780635d99ba831461044e5780636109cdbf1461046d57806366b2d8f91461048c5780636797d24c146104b8578063698766ee146104ec578063715018a61461050b578063765d8b2e1461051f57806378b7d4551461053e5780637aeaa75d1461055d5780637afcdc3c1461057c575f80fd5b366102645761022a61087b565b604080513481523360208201527f49109bdae8e3bbdcbeb7fe5b25b1c75a6bc84fd3f27c6ee0633d41fe197f2aba910160405180910390a1005b5f80fd5b348015610273575f80fd5b506102876102823660046133a7565b6108ac565b005b348015610294575f80fd5b506001546102a990600160a01b900460ff1681565b60405190151581526020015b60405180910390f35b3480156102c9575f80fd5b506102876102d8366004613402565b61095c565b3480156102e8575f80fd5b506102fc6102f736600461342c565b610a05565b6040516102b59190613447565b348015610314575f80fd5b5061033c7f00000000000000000000000044087e105137a5095c008aab6a6530182821f2f081565b6040516102b59190613493565b348015610354575f80fd5b50610287610363366004613402565b610a7b565b348015610373575f80fd5b5061033c61038236600461342c565b60036020525f90815260409020546001600160a01b031681565b3480156103a7575f80fd5b506102876103b63660046134b4565b610b16565b3480156103c6575f80fd5b506103da6103d53660046134ff565b610b59565b6040519081526020016102b5565b3480156103f3575f80fd5b5061028761040236600461342c565b610d7f565b348015610412575f80fd5b5061028761042136600461354f565b610dc8565b348015610431575f80fd5b50610287610e0b565b348015610445575f80fd5b506103da610e26565b348015610459575f80fd5b5061028761046836600461342c565b610fd2565b348015610478575f80fd5b506102876104873660046133a7565b61104c565b348015610497575f80fd5b506104ab6104a636600461342c565b611113565b6040516102b59190613566565b3480156104c3575f80fd5b506104d76104d2366004613402565b6111ae565b604080519283526020830191909152016102b5565b3480156104f7575f80fd5b506102876105063660046135a6565b61133f565b348015610516575f80fd5b50610287611460565b34801561052a575f80fd5b5060085461033c906001600160a01b031681565b348015610549575f80fd5b506103da61055836600461360c565b6114ac565b348015610568575f80fd5b5061028761057736600461364a565b6117ff565b348015610587575f80fd5b50610287610596366004613737565b611a78565b3480156105a6575f80fd5b5061033c7f0000000000000000000000008c237520a8e14d658170a633d96f8e80764433b981565b3480156105d9575f80fd5b506103da60075481565b3480156105ee575f80fd5b5061033c7f0000000000000000000000007bb12bcac1108ff996a3794ed6a77dac5565fec881565b348015610621575f80fd5b506102876106303660046134b4565b611e11565b348015610640575f80fd5b506102a961064f36600461342c565b611e4d565b34801561065f575f80fd5b506102a961066e36600461342c565b60056020525f908152604090205460ff1681565b34801561068d575f80fd5b5061028761069c36600461360c565b611ed7565b3480156106ac575f80fd5b506102876106bb36600461342c565b611f3f565b3480156106cb575f80fd5b506103da6106da36600461342c565b611fb9565b3480156106ea575f80fd5b506102876106f9366004613402565b612129565b348015610709575f80fd5b506102876107183660046137b5565b6121db565b348015610728575f80fd5b5060015461033c906001600160a01b031681565b348015610747575f80fd5b506103da60025481565b34801561075c575f80fd5b506103da61227f565b348015610770575f80fd5b506006546103da565b348015610784575f80fd5b5061033c61079336600461354f565b61228d565b3480156107a3575f80fd5b506102876107b2366004613402565b6122b5565b3480156107c2575f80fd5b506102876107d1366004613894565b612307565b3480156107e1575f80fd5b50610287612518565b3480156107f5575f80fd5b505f5461033c906001600160a01b031681565b348015610813575f80fd5b5061082761082236600461342c565b61259e565b6040516102b59190613973565b34801561083f575f80fd5b506103da612606565b348015610853575f80fd5b5061033c7f0000000000000000000000004f30a9d41b80ecc5b94306ab4364951ae317021081565b60018054600160a01b900460ff16151590036108aa5760405163012a9bc160e01b815260040160405180910390fd5b565b6108b461260f565b6008545f54604051630f44fe1d60e21b81526001600160a01b0392831692633d13f874926108ed929116908790879087906004016139da565b5f604051808303815f87803b158015610904575f80fd5b505af1158015610916573d5f803e3d5ffd5b505050507ff50d70ea1da361101e246009eff066a75f0618b780f16e1314d100b0d324b37f8383834260405161094f9493929190613a01565b60405180910390a1505050565b8161096681612631565b6001600160a01b0383165f9081526004602052604090206002810180546109b39186918690811061099957610999613a2b565b5f918252602090912001546001600160a01b03163061266d565b8160010184815481106109c8576109c8613a2b565b905f5260205f2090600291828204019190066010026101000a8154816001600160801b0302191690836001600160801b0316021790555050505050565b6001600160a01b0381165f90815260046020908152604091829020600201805483518184028101840190945280845260609392830182828015610a6f57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610a51575b50505050509050919050565b610a83612682565b6001600160a01b038083165f908152600360205260409020541680610abb57604051630d23cf4160e11b815260040160405180910390fd5b604051638caad7b560e01b8152600481018390526001600160a01b03821690638caad7b5906024015b5f604051808303815f87803b158015610afb575f80fd5b505af1158015610b0d573d5f803e3d5ffd5b50505050505050565b610b1e612682565b5f610b28836126ae565b604051633951707760e01b815283151560048201529091506001600160a01b03821690633951707790602401610ae4565b5f610b62612682565b610b6a612518565b5f610b736126eb565b90505f83610b8957610b8486612707565b610b8b565b815b905081816001600160801b03161015610bb757604051636badcecf60e01b815260040160405180910390fd5b8615610c3d57610c087f000000000000000000000000808507121b80c02388fad14726482e061b8da8277f0000000000000000000000004f30a9d41b80ecc5b94306ab4364951ae317021089612741565b8415155f03610c3d57610c3d7f000000000000000000000000808507121b80c02388fad14726482e061b8da82733308a6127aa565b6040516364090f6160e11b81526001600160801b038089166004830152821660248201527f0000000000000000000000004f30a9d41b80ecc5b94306ab4364951ae31702106001600160a01b03169063c8121ec2906044016020604051808303815f875af1158015610cb1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cd59190613a3f565b6001600160801b03169250610ce8612518565b8415155f03610cf8575050610d77565b8615610d15578660025f828254610d0f9190613a6e565b90915550505b604080518881526001600160801b0383166020820152908101849052851515606082015284151560808201524260a08201527f81c3ffd68d2582ce8b110372b88b1620a58f73a45fb2fa70a32000c1f411037b9060c00160405180910390a150505b949350505050565b80610d8981612631565b6001600160a01b0382165f908152600460205260408120600201545b80821015610dc257610db7848361095c565b816001019150610da5565b50505050565b610dd0612682565b60078190556040518181527f3ee3809877d53d55716573bfb8d95c61d9bbd6eb4785bf652ede115adb0f87c19060200160405180910390a150565b610e136127e9565b5f80546001600160a01b03191633179055565b5f610e2f612682565b7f000000000000000000000000000000000000000000000000000000000000000115155f03610ed45750600280545f918290559054610e99907f000000000000000000000000808507121b80c02388fad14726482e061b8da827906001600160a01b031683612816565b604080518281524260208201527ffb86642c6ff183cbd0d7b3c84eff3ef09ab5f598dcf85a45790297f3e5072817910160405180910390a190565b42610edd6126eb565b1115610efc5760405163d0404f8560e01b815260040160405180910390fd5b610f04612518565b7f0000000000000000000000004f30a9d41b80ecc5b94306ab4364951ae31702106001600160a01b0316633ccfd60b6040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610f61573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f859190613a3f565b5f546001600160801b03919091169150610fca907f000000000000000000000000808507121b80c02388fad14726482e061b8da827906001600160a01b031683612816565b610e99612518565b80610fdc81612631565b6001600160a01b0382165f90815260046020526040902060028101546001600160401b0381111561100f5761100f613681565b604051908082528060200260200182016040528015611038578160200160208202803683370190505b508051610dc2918391602090910190613200565b6040516253f6a760e41b81526001600160a01b037f0000000000000000000000008c237520a8e14d658170a633d96f8e80764433b9169063053f6a709061109d9030908790879087906004016139da565b6020604051808303815f875af11580156110b9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110dd9190613a81565b507f7dae5ae135d483810fba324b0121ba1b97bd34e06e2c8449ba001c42df198db18383834260405161094f9493929190613a01565b6001600160a01b0381165f90815260046020908152604091829020600101805483518184028101840190945280845260609392830182828015610a6f57602002820191905f5260205f20905f905b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f01049283019260010382029150808411611161575094979650505050505050565b5f80836111ba81612835565b835f036111da57604051639811e0c760e01b815260040160405180910390fd5b6001600160a01b038086165f908152600360205260408120549091169061122a7f000000000000000000000000808507121b80c02388fad14726482e061b8da82761122584896128b7565b61294f565b90508060025f82825461123d9190613a98565b9091555061126f90507f000000000000000000000000808507121b80c02388fad14726482e061b8da8273330846127aa565b604051633e87f6d560e11b8152600481018790525f906001600160a01b03841690637d0fedaa906024016020604051808303815f875af11580156112b5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112d99190613a81565b90506112e6883383612816565b60408051888152602081018490529081018290526001600160a01b038916907f049425cdb07b8722657d13dbc0cdaa252f471025bd8fd8455486016e71df972e9060600160405180910390a29097909650945050505050565b611347612682565b8083146113675760405163251f56a160e21b815260040160405180910390fd5b5f81815b818310156113af5784848481811061138557611385613a2b565b905060200201602081019061139a9190613ac1565b6001909301926001600160401b03160161136b565b670de0b6b3a76400008111156113d85760405163940addc760e01b815260040160405180910390fd5b6040516334c3b37760e11b81526001600160a01b037f00000000000000000000000044087e105137a5095c008aab6a6530182821f2f0169063698766ee9061142a908a908a908a908a90600401613ada565b5f604051808303815f87803b158015611441575f80fd5b505af1158015611453573d5f803e3d5ffd5b5050505050505050505050565b611468612682565b5f80546001600160a01b0319908116825560018054909116905560405133917f6172baf984ea013d88b784409f46655b96ba7f2ff91bca1ac9bcd27b113e6eb091a2565b5f836114b781612835565b6001600160a01b0385165f908152600460209081526040808320815181546080948102820185019093526060810183815290939192849284919084018282801561151e57602002820191905f5260205f20905b81548152602001906001019080831161150a575b50505050508152602001600182018054806020026020016040519081016040528092919081815260200182805480156115a557602002820191905f5260205f20905f905b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f010492830192600103820291508084116115625790505b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561160557602002820191905f5260205f20905b81546001600160a01b031681526001909101906020018083116115e7575b50505050508152505090505f61161f8260400151876129ac565b905084825f0151828151811061163757611637613a2b565b6020026020010151101561165e57604051632d23af9d60e21b815260040160405180910390fd5b5f61166d8861122589896128b7565b905085835f0151838151811061168557611685613a2b565b602002602001018181516116999190613a6e565b9052506001600160a01b0388165f9081526004602090815260409091208451805186936116ca928492910190613200565b5060208281015180516116e39260018501920190613249565b50604082015180516116ff9160028401916020909101906132f9565b5090505061170f883330846127aa565b6001600160a01b038881165f9081526003602052604090819020549051636ae55c3f60e01b815260048101849052911690636ae55c3f906024015f604051808303815f87803b158015611760575f80fd5b505af1158015611772573d5f803e3d5ffd5b5050505061179e8360400151838151811061178f5761178f613a2b565b60200260200101513388612816565b866001600160a01b0316886001600160a01b03167f7497b44341cf7a330eb32a7dedfb6e54b3e0ba937271da2d52025bd49667135488846040516117ec929190918252602082015260400190565b60405180910390a3979650505050505050565b8261180981612631565b6001600160a01b0384165f908152600460209081526040808320815181546080948102820185019093526060810183815290939192849284919084018282801561187057602002820191905f5260205f20905b81548152602001906001019080831161185c575b50505050508152602001600182018054806020026020016040519081016040528092919081815260200182805480156118f757602002820191905f5260205f20905f905b82829054906101000a90046001600160801b03166001600160801b031681526020019060100190602082600f010492830192600103820291508084116118b45790505b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561195757602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611939575b50505050508152505090505f8082604001515190505b808210156119c55785858381811061198757611987613a2b565b90506020020135835f015183815181106119a3576119a3613a2b565b602002602001018181516119b79190613a98565b90525060019091019061196d565b6001600160a01b0387165f9081526004602090815260409091208451805186936119f3928492910190613200565b506020828101518051611a0c9260018501920190613249565b5060408201518051611a289160028401916020909101906132f9565b50905050866001600160a01b03167f501c57a5a0f2fe1ea61d8d78bca856d5aa22562392484491e7c297941464b34f8787604051611a67929190613b6d565b60405180910390a250505050505050565b611a80612682565b6001600160a01b038481165f908152600360205260409020541615611ab85760405163a741a04560e01b815260040160405180910390fd5b602a611ac360065490565b03611ae0576040516274618b60e51b815260040160405180910390fd5b6001600160a01b038416611b0757604051630d23cf4160e11b815260040160405180910390fd5b6040516304fda39f60e21b81525f906001600160a01b037f0000000000000000000000007bb12bcac1108ff996a3794ed6a77dac5565fec816906313f68e7c90611b5b908890889088908890600401613bcd565b6020604051808303815f875af1158015611b77573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b9b9190613c18565b6001600160a01b038681165f90815260036020526040902080546001600160a01b0319169183169190911790559050611bdc85611bd781612a19565b612a7d565b6001600160a01b0385165f9081526004602052604090206002810154806001600160401b03811115611c1057611c10613681565b604051908082528060200260200182016040528015611c39578160200160208202803683370190505b508051611c50916001850191602090910190613249565b50806001600160401b03811115611c6957611c69613681565b604051908082528060200260200182016040528015611c92578160200160208202803683370190505b508051611ca6918491602090910190613200565b505f5b81811015611d66575f836002018281548110611cc757611cc7613a2b565b5f918252602090912001546001600160a01b03169050611ce889823061266d565b846001018381548110611cfd57611cfd613a2b565b905f5260205f2090600291828204019190066010026101000a8154816001600160801b0302191690836001600160801b031602179055505f845f018381548110611d4957611d49613a2b565b5f91825260209091200155611d5d81612ab0565b50600101611ca9565b611d6f88612ab0565b60068054600180820183555f929092527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f0180546001600160a01b0319166001600160a01b038b16179055611dc790899030906121db565b836001600160a01b0316886001600160a01b03167fa832978fceae1f879475bdadef75ee695f5ab7d0d2635bed35d2e9282595352e60405160405180910390a35050505050505050565b611e19612682565b5f611e23836126ae565b6001600160a01b03165f908152600560205260409020805460ff1916921515929092179091555050565b5f81611e5881612631565b5f611e6284612a19565b9050611e6e8482612b64565b1515600103611e80575f925050611ed1565b611e8a8482612a7d565b836001600160a01b03167f096e937b1b3283a0a67ea594d71f0c599b007cc6330f6eb1cfe70e3c455791e782604051611ec39190613447565b60405180910390a260019250505b50919050565b82611ee181612631565b611eec848484612816565b826001600160a01b0316846001600160a01b03167f31947ad95728f2ef65a83a94d3cba12bdc654e728f65f4e91bca53ea5586085f84604051611f3191815260200190565b60405180910390a350505050565b611f47612682565b6001600160a01b038116611f6e5760405163f2365b5b60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03831690811790915560405133907f322fd6444c59daffa82e4689b7685b6fafc6109a1eff8a6ca10c5a8e3206cda1905f90a350565b6001600160a01b038082165f9081526003602052604081205490911680611ff357604051630d23cf4160e11b815260040160405180910390fd5b6040516370a0823160e01b81525f906001600160a01b038516906370a0823190612021903090600401613493565b602060405180830381865afa15801561203c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120609190613a81565b90505f826001600160a01b0316630cd107da6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561209f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120c39190613a81565b90506120d0816001613a98565b8210156120f0576040516316ed654560e31b815260040160405180910390fd5b5f6120fb8284613a6e565b612106906001613a98565b5f549091506121209087906001600160a01b031683612816565b95945050505050565b612131612682565b5f61213b836126ae565b60405163e929d66960e01b8152600481018490529091506001600160a01b0382169063e929d669906024015f604051808303815f87803b15801561217d575f80fd5b505af115801561218f573d5f803e3d5ffd5b50505050826001600160a01b03167f93093390567ab17f0424ef1af14d90a4e2d60ed10df4054eadbd61a400e269c0836040516121ce91815260200190565b60405180910390a2505050565b6121e3612682565b6001600160a01b038084165f90815260036020526040902054168061221b57604051630d23cf4160e11b815260040160405180910390fd5b60405163112d197560e11b81526001600160a01b038481166004830152831515602483015282169063225a32ea906044015f604051808303815f87803b158015612263575f80fd5b505af1158015612275573d5f803e3d5ffd5b5050505050505050565b5f612288612bd6565b905090565b6006818154811061229c575f80fd5b5f918252602090912001546001600160a01b0316905081565b6122bd612682565b60018054600160a01b900460ff16151590036122ec5760405163012a9bc160e01b815260040160405180910390fd5b6122f68282612bef565b50506001805460ff60a01b19169055565b61230f612682565b8151815181146123325760405163251f56a160e21b815260040160405180910390fd5b5f61233b612ca3565b90505f805b838210156124e95784828151811061235a5761235a613a2b565b602002602001015190505f6001600160a01b0316816001600160a01b0316036123965760405163d92e233d60e01b815260040160405180910390fd5b306001600160a01b038216036123bf57604051633f89638160e11b815260040160405180910390fd5b60048683815181106123d3576123d3613a2b565b60200260200101515110156124025760405163b5b4301960e01b81526004810183905260240160405180910390fd5b61242486838151811061241757612417613a2b565b6020026020010151612ded565b15156001036124465760405163853e38d360e01b815260040160405180910390fd5b5f816001600160a01b031687848151811061246357612463613a2b565b60200260200101516040516124789190613c33565b5f604051808303815f865af19150503d805f81146124b1576040519150601f19603f3d011682016040523d82523d5f602084013e6124b6565b606091505b50909150508015155f036124dd57604051630d04919960e11b815260040160405180910390fd5b82600101925050612340565b826124f2612ca3565b1461251057604051632b582cb960e21b815260040160405180910390fd5b505050505050565b6006545f905b8082101561259a575f6006838154811061253a5761253a613a2b565b5f9182526020808320909101546001600160a01b0390811680845260038352604080852054909216845260059092529091205460019485019491925060ff16151514151560010361258b575061251e565b61259481612835565b5061251e565b5050565b6001600160a01b0381165f90815260046020908152604091829020805483518184028101840190945280845260609392830182828015610a6f57602002820191905f5260205f20905b8154815260200190600101908083116125e75750505050509050919050565b5f6122886126eb565b61a4b146146108aa576040516323a7aa6760e11b815260040160405180910390fd5b6001600160a01b038181165f9081526003602052604090205416331461266a57604051631eb49d6d60e11b815260040160405180910390fd5b50565b5f612679848484612e36565b51949350505050565b5f546001600160a01b0316330361269557565b604051635a7617f960e11b815260040160405180910390fd5b6001600160a01b038082165f9081526003602052604090205416806126e657604051630d23cf4160e11b815260040160405180910390fd5b919050565b5f6126f530612eb6565b602001516001600160801b0316905090565b5f8062093a806127178142613c4e565b6127219190613c6d565b905061273062093a8084613c84565b61273a9082613caf565b9392505050565b6001600160a01b03821661275457505050565b610dc28363095ea7b360e01b8484604051602401612773929190613cd6565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612f51565b6040516001600160a01b03808516602483015283166044820152606481018290526127e29085906323b872dd60e01b90608401612773565b5050505050565b6001546001600160a01b031633036127fd57565b6040516379543eaf60e11b815260040160405180910390fd5b610dc28363a9059cbb60e01b8484604051602401612773929190613cd6565b6001600160a01b038082165f90815260036020526040902054168061286d57604051630d23cf4160e11b815260040160405180910390fd5b806001600160a01b031663753d02a16040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156128a5575f80fd5b505af1158015612510573d5f803e3d5ffd5b604051630e8f811d60e41b81525f906001600160a01b037f000000000000000000000000896fc8ffc11cda80cf40c373afa9a22d6e05f2d3169063e8f811d0906129079086908690600401613cd6565b602060405180830381865afa158015612922573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129469190613a81565b90505b92915050565b5f80620f4240600754620f42406129669190613a6e565b6129709085613c6d565b61297a9190613c4e565b90506402540be4008110156129a257604051639a721da360e01b815260040160405180910390fd5b610d778482613006565b81515f9081905b80821015612a0057836001600160a01b03168583815181106129d7576129d7613a2b565b60200260200101516001600160a01b0316036129f557509050612949565b8160010191506129b3565b60405163c5723b5160e01b815260040160405180910390fd5b6060816001600160a01b031663c4f59f9b6040518163ffffffff1660e01b81526004015f60405180830381865afa158015612a56573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526129499190810190613cef565b6001600160a01b0382165f9081526004602090815260409091208251612aab926002909201918401906132f9565b505050565b604051630fea45cd60e11b81525f907f000000000000000000000000896fc8ffc11cda80cf40c373afa9a22d6e05f2d36001600160a01b031690631fd48b9a90612afe908590600401613493565b602060405180830381865afa158015612b19573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b3d9190613c18565b6001600160a01b03160361266a57604051630d23cf4160e11b815260040160405180910390fd5b6001600160a01b0382165f9081526004602090815260408083209051612b909260029092019101613d83565b6040516020818303038152906040528051906020012082604051602001612bb79190613447565b6040516020818303038152906040528051906020012014905092915050565b5f612be030612eb6565b516001600160801b0316919050565b80471015612c105760405163617ab12d60e11b815260040160405180910390fd5b6001805460ff60a01b1916600160a01b1790556040515f906001600160a01b0384169083908381818185875af1925050503d805f8114612c6b576040519150601f19603f3d011682016040523d82523d5f602084013e612c70565b606091505b50506001805460ff60a01b1916905590508015155f03612aab5760405163120086e360e11b815260040160405180910390fd5b5f807f000000000000000000000000808507121b80c02388fad14726482e061b8da8276001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401612cf19190613493565b602060405180830381865afa158015612d0c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d309190613a81565b6040515f602082018190526034820181905291925060540160408051601f19818403018152828252805160209182012090830152810183905260600160408051601f1981840301815291905280516020909101206006549091505f9081905b80831015612de35760068381548110612daa57612daa613a2b565b5f918252602090912001546001600160a01b03169150612dca8285613056565b9350612dd68483613163565b9350826001019250612d8f565b5091949350505050565b60208101515f9063f6a1584d60e01b6001600160e01b0319821601612e155750600192915050565b632afa533160e01b6001600160e01b0319821601611ed15750600192915050565b6040805180820182525f8082526020820152905163172eb6f960e21b81526001600160a01b0384811660048301528381166024830152851690635cbadbe4906044016040805180830381865afa158015612e92573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d779190613e28565b6040805180820182525f808252602082015290516332dad3cf60e21b81527f0000000000000000000000004f30a9d41b80ecc5b94306ab4364951ae31702106001600160a01b03169063cb6b4f3c90612f13908590600401613493565b6040805180830381865afa158015612f2d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129499190613e28565b5f805f846001600160a01b031684604051612f6c9190613c33565b5f604051808303815f865af19150503d805f8114612fa5576040519150601f19603f3d011682016040523d82523d5f602084013e612faa565b606091505b50915091505f81515f1480612fce575081806020019051810190612fce9190613e42565b90508215155f03612fdd575f80fd5b828015612fe75750805b8015612ffc57505f866001600160a01b03163b115b9695505050505050565b6040516326a7a5ed60e21b81525f906001600160a01b037f000000000000000000000000896fc8ffc11cda80cf40c373afa9a22d6e05f2d31690639a9e97b4906129079086908690600401613cd6565b6001600160a01b0382165f908152600460209081526040808320600201805482518185028101850190935280835284938301828280156130bd57602002820191905f5260205f20905b81546001600160a01b0316815260019091019060200180831161309f575b505083519394505f925050505b81811015613159577f000000000000000000000000808507121b80c02388fad14726482e061b8da8276001600160a01b031683828151811061310e5761310e613a2b565b60200260200101516001600160a01b03160361312c576001016130ca565b61314f8584838151811061314257613142613a2b565b6020026020010151613163565b94506001016130ca565b5092949350505050565b5f82826001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016131919190613493565b602060405180830381865afa1580156131ac573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131d09190613a81565b60408051602081019390935282015260600160405160208183030381529060405280519060200120905092915050565b828054828255905f5260205f20908101928215613239579160200282015b8281111561323957825182559160200191906001019061321e565b5061324592915061334c565b5090565b828054828255905f5260205f2090600101600290048101928215613239579160200282015f5b838211156132b957835183826101000a8154816001600160801b0302191690836001600160801b031602179055509260200192601001602081600f0104928301926001030261326f565b80156132ec5782816101000a8154906001600160801b030219169055601001602081600f010492830192600103026132b9565b505061324592915061334c565b828054828255905f5260205f20908101928215613239579160200282015b8281111561323957825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613317565b5b80821115613245575f815560010161334d565b5f8083601f840112613370575f80fd5b5081356001600160401b03811115613386575f80fd5b6020830191508360208260051b85010111156133a0575f80fd5b9250929050565b5f805f604084860312156133b9575f80fd5b8335925060208401356001600160401b038111156133d5575f80fd5b6133e186828701613360565b9497909650939450505050565b6001600160a01b038116811461266a575f80fd5b5f8060408385031215613413575f80fd5b823561341e816133ee565b946020939093013593505050565b5f6020828403121561343c575f80fd5b813561273a816133ee565b602080825282518282018190525f9190848201906040850190845b818110156134875783516001600160a01b031683529284019291840191600101613462565b50909695505050505050565b6001600160a01b0391909116815260200190565b801515811461266a575f80fd5b5f80604083850312156134c5575f80fd5b82356134d0816133ee565b915060208301356134e0816134a7565b809150509250929050565b6001600160801b038116811461266a575f80fd5b5f805f8060808587031215613512575f80fd5b843593506020850135613524816134eb565b92506040850135613534816134a7565b91506060850135613544816134a7565b939692955090935050565b5f6020828403121561355f575f80fd5b5035919050565b602080825282518282018190525f9190848201906040850190845b818110156134875783516001600160801b031683529284019291840191600101613581565b5f805f80604085870312156135b9575f80fd5b84356001600160401b03808211156135cf575f80fd5b6135db88838901613360565b909650945060208701359150808211156135f3575f80fd5b5061360087828801613360565b95989497509550505050565b5f805f6060848603121561361e575f80fd5b8335613629816133ee565b92506020840135613639816133ee565b929592945050506040919091013590565b5f805f6040848603121561365c575f80fd5b8335613667816133ee565b925060208401356001600160401b038111156133d5575f80fd5b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b03811182821017156136bd576136bd613681565b604052919050565b5f6001600160401b038311156136dd576136dd613681565b6136f0601f8401601f1916602001613695565b9050828152838383011115613703575f80fd5b828260208301375f602084830101529392505050565b5f82601f830112613728575f80fd5b612946838335602085016136c5565b5f805f806080858703121561374a575f80fd5b8435613755816133ee565b935060208501356001600160401b0380821115613770575f80fd5b61377c88838901613719565b94506040870135915080821115613791575f80fd5b5061379e87828801613719565b925050606085013561ffff81168114613544575f80fd5b5f805f606084860312156137c7575f80fd5b83356137d2816133ee565b925060208401356137e2816133ee565b915060408401356137f2816134a7565b809150509250925092565b5f6001600160401b0382111561381557613815613681565b5060051b60200190565b5f82601f83011261382e575f80fd5b8135602061384361383e836137fd565b613695565b8083825260208201915060208460051b870101935086841115613864575f80fd5b602086015b8481101561388957803561387c816133ee565b8352918301918301613869565b509695505050505050565b5f8060408084860312156138a6575f80fd5b83356001600160401b03808211156138bc575f80fd5b818601915086601f8301126138cf575f80fd5b813560206138df61383e836137fd565b82815260059290921b8401810191818101908a8411156138fd575f80fd5b8286015b8481101561394557803586811115613917575f80fd5b8701603f81018d13613927575f80fd5b6139378d868301358b84016136c5565b845250918301918301613901565b509750508701359350508083111561395b575f80fd5b50506139698582860161381f565b9150509250929050565b602080825282518282018190525f9190848201906040850190845b818110156134875783518352928401929184019160010161398e565b8183525f6001600160fb1b038311156139c1575f80fd5b8260051b80836020870137939093016020019392505050565b60018060a01b0385168152836020820152606060408201525f612ffc6060830184866139aa565b848152606060208201525f613a1a6060830185876139aa565b905082604083015295945050505050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215613a4f575f80fd5b815161273a816134eb565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561294957612949613a5a565b5f60208284031215613a91575f80fd5b5051919050565b8082018082111561294957612949613a5a565b80356001600160401b03811681146126e6575f80fd5b5f60208284031215613ad1575f80fd5b61294682613aab565b604080825281018490525f8560608301825b87811015613b1c578235613aff816133ee565b6001600160a01b0316825260209283019290910190600101613aec565b508381036020858101919091528582529150859082015f5b86811015613b60576001600160401b03613b4d84613aab565b1682529183019190830190600101613b34565b5098975050505050505050565b602081525f610d776020830184866139aa565b5f5b83811015613b9a578181015183820152602001613b82565b50505f910152565b5f8151808452613bb9816020860160208601613b80565b601f01601f19169290920160200192915050565b6001600160a01b03851681526080602082018190525f90613bf090830186613ba2565b8281036040840152613c028186613ba2565b91505061ffff8316606083015295945050505050565b5f60208284031215613c28575f80fd5b815161273a816133ee565b5f8251613c44818460208701613b80565b9190910192915050565b5f82613c6857634e487b7160e01b5f52601260045260245ffd5b500490565b808202811582820484141761294957612949613a5a565b6001600160801b03818116838216028082169190828114613ca757613ca7613a5a565b505092915050565b6001600160801b03818116838216019080821115613ccf57613ccf613a5a565b5092915050565b6001600160a01b03929092168252602082015260400190565b5f6020808385031215613d00575f80fd5b82516001600160401b03811115613d15575f80fd5b8301601f81018513613d25575f80fd5b8051613d3361383e826137fd565b81815260059190911b82018301908381019087831115613d51575f80fd5b928401925b82841015613d78578351613d69816133ee565b82529284019290840190613d56565b979650505050505050565b602080825282548282018190525f8481528281209092916040850190845b818110156134875783546001600160a01b031683526001938401939285019201613da1565b5f60408284031215613dd6575f80fd5b604051604081018181106001600160401b0382111715613df857613df8613681565b80604052508091508251613e0b816134eb565b81526020830151613e1b816134eb565b6020919091015292915050565b5f60408284031215613e38575f80fd5b6129468383613dc6565b5f60208284031215613e52575f80fd5b815161273a816134a756fea2646970667358221220fd69f09e97dec70526f29ea18411f9171b2c9ec771961a602b4a3978a15d023164736f6c63430008190033
Verified Source Code Full Match
Compiler: v0.8.25+commit.b61c2a91
EVM: shanghai
Optimization: Yes (20 runs)
OwnableMaster.sol 114 lines
// SPDX-License-Identifier: -- WISE --
pragma solidity =0.8.25;
error NoValue();
error NotMaster();
error NotProposed();
contract OwnableMaster {
address public master;
address public proposedMaster;
address internal constant ZERO_ADDRESS = address(0x0);
modifier onlyProposed() {
_onlyProposed();
_;
}
function _onlyMaster()
private
view
{
if (msg.sender == master) {
return;
}
revert NotMaster();
}
modifier onlyMaster() {
_onlyMaster();
_;
}
function _onlyProposed()
private
view
{
if (msg.sender == proposedMaster) {
return;
}
revert NotProposed();
}
event MasterProposed(
address indexed proposer,
address indexed proposedMaster
);
event RenouncedOwnership(
address indexed previousMaster
);
constructor(
address _master
) {
if (_master == ZERO_ADDRESS) {
revert NoValue();
}
master = _master;
}
/**
* @dev Allows to propose next master.
* Must be claimed by proposer.
*/
function proposeOwner(
address _proposedOwner
)
external
onlyMaster
{
if (_proposedOwner == ZERO_ADDRESS) {
revert NoValue();
}
proposedMaster = _proposedOwner;
emit MasterProposed(
msg.sender,
_proposedOwner
);
}
/**
* @dev Allows to claim master role.
* Must be called by proposer.
*/
function claimOwnership()
external
onlyProposed
{
master = msg.sender;
}
/**
* @dev Removes master role.
* No ability to be in control.
*/
function renounceOwnership()
external
onlyMaster
{
master = ZERO_ADDRESS;
proposedMaster = ZERO_ADDRESS;
emit RenouncedOwnership(
msg.sender
);
}
}
IERC20.sol 75 lines
// SPDX-License-Identifier: -- WISE --
pragma solidity =0.8.25;
interface IERC20 {
function totalSupply()
external
view
returns (uint256);
function balanceOf(
address _account
)
external
view
returns (uint256);
function transferFrom(
address _sender,
address _recipient,
uint256 _amount
)
external
returns (bool);
function transfer(
address _recipient,
uint256 _amount
)
external
returns (bool);
function allowance(
address owner,
address spender
)
external
view
returns (uint256);
function approve(
address _spender,
uint256 _amount
)
external
returns (bool);
function decimals()
external
view
returns (uint8);
event Transfer(
address indexed from,
address indexed to,
uint256 value
);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
event Deposit(
address indexed dst,
uint wad
);
event Withdrawal(
address indexed src,
uint wad
);
}
IPendle.sol 619 lines
// SPDX-License-Identifier: -- WISE --
pragma solidity =0.8.25;
import {IERC20 as IERC20A} from "./IERC20.sol";
struct Order {
uint256 salt;
uint256 expiry;
uint256 nonce;
IPLimitOrderType.OrderType orderType;
address token;
address YT;
address maker;
address receiver;
uint256 makingAmount;
uint256 lnImpliedRate;
uint256 failSafeRate;
bytes permit;
}
struct FillOrderParams {
Order order;
bytes signature;
uint256 makingAmount;
}
struct TokenOutput {
// TOKEN DATA
address tokenOut;
uint256 minTokenOut;
address tokenRedeemSy;
// AGGREGATOR DATA
address pendleSwap;
SwapData swapData;
}
struct LimitOrderData {
address limitRouter;
uint256 epsSkipMarket; // only used for swap
// operations, will be ignored otherwise
FillOrderParams[] normalFills;
FillOrderParams[] flashFills;
bytes optData;
}
struct TokenInput {
// TOKEN DATA
address tokenIn;
uint256 netTokenIn;
address tokenMintSy;
// AGGREGATOR DATA
address pendleSwap;
SwapData swapData;
}
enum SwapType {
NONE,
KYBERSWAP,
ONE_INCH,
// ETH_WETH not used in Aggregator
ETH_WETH
}
struct SwapData {
SwapType swapType;
address extRouter;
bytes extCalldata;
bool needScale;
}
struct MarketStorage {
int128 totalPt;
int128 totalSy;
uint96 lastLnImpliedRate;
uint16 observationIndex;
uint16 observationCardinality;
uint16 observationCardinalityNext;
}
struct FillResults {
uint256 totalMaking;
uint256 totalTaking;
uint256 totalFee;
uint256 totalNotionalVolume;
uint256[] netMakings;
uint256[] netTakings;
uint256[] netFees;
uint256[] notionalVolumes;
}
struct MarketState {
int256 totalPt;
int256 totalSy;
int256 totalLp;
address treasury;
int256 scalarRoot;
uint256 expiry;
uint256 lnFeeRateRoot;
uint256 reserveFeePercent;
uint256 lastLnImpliedRate;
}
struct LockedPosition {
uint128 amount;
uint128 expiry;
}
struct UserReward {
uint128 index;
uint128 accrued;
}
struct ApproxParams {
uint256 guessMin;
uint256 guessMax;
uint256 guessOffchain;
uint256 maxIteration;
uint256 eps;
}
interface IPendleSy {
function decimals()
external
view
returns (uint8);
function previewDeposit(
address _tokenIn,
uint256 _amountTokenToDeposit
)
external
view
returns (uint256 sharesAmount);
function deposit(
address _receiver,
address _tokenIn,
uint256 _amountTokenToDeposit,
uint256 _minSharesOut
)
external
returns (uint256 sharesAmount);
function exchangeRate()
external
view
returns (uint256);
function redeem(
address _receiver,
uint256 _amountSharesToRedeem,
address _tokenOut,
uint256 _minTokenOut,
bool _burnFromInternalBalance
)
external
returns (uint256 amountTokenOut);
}
interface IPendleYt {
function mintPY(
address _receiverPT,
address _receiverYT
)
external
returns (uint256 pyAmount);
function redeemPY(
address _receiver
)
external
returns (uint256);
function redeemDueInterestAndRewards(
address _user,
bool _redeemInterest,
bool _redeemRewards
)
external
returns (
uint256 interestOut,
uint256[] memory rewardsOut
);
function getRewardTokens()
external
view
returns (address[] memory);
function userReward(
address _token,
address _user
)
external
view
returns (UserReward memory);
function userInterest(
address user
)
external
view
returns (
uint128 lastPYIndex,
uint128 accruedInterest
);
function pyIndexStored()
external
view
returns (uint256);
}
interface IPendleMarket {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
)
external;
function readTokens()
external
view
returns (
address SY,
address PT,
address YT
);
function activeBalance(
address _user
)
external
view
returns (uint256);
function transferFrom(
address _from,
address _to,
uint256 _amount
)
external;
function balanceOf(
address _user
)
external
view
returns (uint256);
function isExpired()
external
view
returns (bool);
function decimals()
external
view
returns (uint8);
function increaseObservationsCardinalityNext(
uint16 _newObservationCardinalityNext
)
external;
function swapExactPtForSy(
address receiver,
uint256 exactPtIn,
bytes calldata data
)
external
returns (
uint256 netSyOut,
uint256 netSyFee
);
function _storage()
external
view
returns (MarketStorage memory);
function getRewardTokens()
external
view
returns (address[] memory);
function readState(
address _router
)
external
view
returns (MarketState memory marketState);
function mint(
address _receiver,
uint256 _netSyDesired,
uint256 _netPtDesired
)
external
returns (uint256[3] memory);
function burn(
address _receiverAddressSy,
address _receiverAddressPt,
uint256 _lpToBurn
)
external
returns (
uint256 syOut,
uint256 ptOut
);
function redeemRewards(
address _user
)
external
returns (uint256[] memory);
function totalSupply()
external
view
returns (uint256);
function userReward(
address _token,
address _user
)
external
view
returns (UserReward memory);
}
interface IPendleChild {
function underlyingLpAssetsCurrent()
external
view
returns (uint256);
function totalLpAssets()
external
view
returns (uint256);
function totalSupply()
external
view
returns (uint256);
function previewUnderlyingLpAssets()
external
view
returns (uint256);
function previewMintShares(
uint256 _underlyingAssetAmount,
uint256 _underlyingLpAssetsCurrent
)
external
view
returns (uint256);
function previewAmountWithdrawShares(
uint256 _shares,
uint256 _underlyingLpAssetsCurrent
)
external
view
returns (uint256);
function previewBurnShares(
uint256 _underlyingAssetAmount,
uint256 _underlyingLpAssetsCurrent
)
external
view
returns (uint256);
function depositExactAmount(
uint256 _amount
)
external
returns (
uint256,
uint256
);
function withdrawExactShares(
uint256 _shares
)
external
returns (uint256);
}
interface IPendleLock {
function increaseLockPosition(
uint128 _additionalAmountToLock,
uint128 _newExpiry
)
external
returns (uint128 newVeBalance);
function withdraw()
external
returns (uint128);
function positionData(
address _user
)
external
view
returns (LockedPosition memory);
function getBroadcastPositionFee(
uint256[] calldata _chainIds
)
external
view
returns (uint256);
}
interface IPendleVoteRewards {
function claimRetail(
address _user,
uint256 _amount,
bytes32[] calldata _merkleProof
)
external
returns (uint256);
}
interface IPendleVoter {
function vote(
address[] memory _pools,
uint64[] memory _weights
)
external;
}
interface IPLimitOrderType {
enum OrderType {
SY_FOR_PT,
PT_FOR_SY,
SY_FOR_YT,
YT_FOR_SY
}
// Fixed-size order part with core information
struct StaticOrder {
uint256 salt;
uint256 expiry;
uint256 nonce;
OrderType orderType;
address token;
address YT;
address maker;
address receiver;
uint256 makingAmount;
uint256 lnImpliedRate;
uint256 failSafeRate;
}
}
interface IPendleRouter {
function removeLiquiditySingleToken(
address receiver,
address market,
uint256 netLpToRemove,
TokenOutput calldata output,
LimitOrderData calldata limit
)
external
returns (
uint256 netTokenOut,
uint256 netSyFee,
uint256 netSyInterm
);
function swapTokenToToken(
address receiver,
uint256 minTokenOut,
TokenInput memory inp
)
external
payable
returns (uint256 netTokenOut);
function addLiquiditySingleToken(
address receiver,
address market,
uint256 minLpOut,
ApproxParams memory guessPtReceivedFromSy,
TokenInput memory input,
LimitOrderData memory limit
)
external
payable
returns (
uint256 netLpOut,
uint256 netSyFee,
uint256 netSyInterm
);
function swapSyForExactYt(
address _receiver,
address _market,
uint256 _exactYtOut,
uint256 _maxSyIn
)
external
returns (
uint256 netSyIn,
uint256 netSyFee
);
function swapExactSyForYt(
address _receiver,
address _market,
uint256 _exactSyIn,
uint256 _minYtOut
)
external
returns (
uint256 netYtOut,
uint256 netSyFee
);
function swapSyForExactPt(
address _receiver,
address _market,
uint256 _exactPtOut,
uint256 _maxSyIn
)
external
returns (
uint256 netSyIn,
uint256 netSyFee
);
function swapExactSyForPt(
address _receiver,
address _market,
uint256 _exactSyIn,
uint256 _minPtOut
)
external
returns (
uint256 netPtOut,
uint256 netSyFee
);
function removeLiquiditySingleSy(
address _receiver,
address _market,
uint256 _netLpToRemove,
uint256 _minSyOut
)
external
returns (
uint256 netSyOut,
uint256 netSyFee
);
function addLiquiditySingleSy(
address _receiver,
address _market,
uint256 _netSyIn,
uint256 _minLpOut,
ApproxParams calldata _guessPtReceivedFromSy
)
external
returns (
uint256 netLpOut,
uint256 netSyFee
);
}
interface IPendleRouterStatic {
function addLiquiditySingleSyStatic(
address _market,
uint256 _netSyIn
)
external
view
returns (
uint256 netLpOut,
uint256 netPtFromSwap,
uint256 netSyFee,
uint256 priceImpact,
uint256 exchangeRateAfter,
uint256 netSyToSwap
);
function swapExactPtForSyStatic(
address _market,
uint256 _exactPtIn
)
external
view
returns (
uint256 netSyOut,
uint256 netSyFee,
uint256 priceImpact,
uint256 exchangeRateAfter
);
}
ApprovalHelper.sol 33 lines
// SPDX-License-Identifier: -- WISE --
pragma solidity =0.8.25;
import "./CallOptionalReturn.sol";
contract ApprovalHelper is CallOptionalReturn {
/**
* @dev
* Allows to execute safe approve for a token
*/
function _safeApprove(
address _token,
address _spender,
uint256 _value
)
internal
{
if (_spender == address(0)) {
return;
}
_callOptionalReturn(
_token,
abi.encodeWithSelector(
IERC20.approve.selector,
_spender,
_value
)
);
}
}
TransferHelper.sol 52 lines
// SPDX-License-Identifier: -- WISE --
pragma solidity =0.8.25;
import "./CallOptionalReturn.sol";
contract TransferHelper is CallOptionalReturn {
/**
* @dev
* Allows to execute safe transfer for a token
*/
function _safeTransfer(
address _token,
address _to,
uint256 _value
)
internal
{
_callOptionalReturn(
_token,
abi.encodeWithSelector(
IERC20.transfer.selector,
_to,
_value
)
);
}
/**
* @dev
* Allows to execute safe transferFrom for a token
*/
function _safeTransferFrom(
address _token,
address _from,
address _to,
uint256 _value
)
internal
{
_callOptionalReturn(
_token,
abi.encodeWithSelector(
IERC20.transferFrom.selector,
_from,
_to,
_value
)
);
}
}
IWiseOracleHub.sol 104 lines
// SPDX-License-Identifier: -- WISE --
pragma solidity =0.8.25;
interface IWiseOracleHub {
function getTokensPriceFromUSD(
address _tokenAddress,
uint256 _usdValue
)
external
view
returns (uint256);
function getTokensPriceInUSD(
address _tokenAddress,
uint256 _tokenAmount
)
external
view
returns (uint256);
function latestResolver(
address _tokenAddress
)
external
view
returns (uint256);
function latestResolverTwap(
address _tokenAddress
)
external
view
returns (uint256);
function getTokensFromUSD(
address _tokenAddress,
uint256 _usdValue
)
external
view
returns (uint256);
function getTokensFromETH(
address _tokenAddress,
uint256 _ethValue
)
external
view
returns (uint256);
function getTokensInUSD(
address _tokenAddress,
uint256 _amount
)
external
view
returns (uint256);
function getTokensInETH(
address _tokenAddress,
uint256 _tokenAmount
)
external
view
returns (uint256);
function chainLinkIsDead(
address _tokenAddress
)
external
view
returns (bool);
function decimalsUSD()
external
pure
returns (uint8);
function addOracle(
address _tokenAddress,
address _priceFeedAddress,
address[] calldata _underlyingFeedTokens
)
external;
function recalibrate(
address _tokenAddress
)
external;
function WETH_ADDRESS()
external
view
returns (address);
function priceFeed(
address _tokenAddress
)
external
view
returns (address);
}
SendValueHelper.sol 37 lines
// SPDX-License-Identifier: -- WISE --
pragma solidity =0.8.25;
error AmountTooSmall();
error SendValueFailed();
contract SendValueHelper {
bool public sendingProgress;
function _sendValue(
address _recipient,
uint256 _amount
)
internal
{
if (address(this).balance < _amount) {
revert AmountTooSmall();
}
sendingProgress = true;
(
bool success
,
) = payable(_recipient).call{
value: _amount
}("");
sendingProgress = false;
if (success == false) {
revert SendValueFailed();
}
}
}
IPendleController.sol 68 lines
// SPDX-License-Identifier: -- WISE --
pragma solidity =0.8.25;
interface IPendleController {
struct compoundStruct {
uint256[] reservedForCompound;
uint128[] lastIndex;
address[] rewardTokens;
}
function withdrawLp(
address _pendleMarket,
address _to,
uint256 _amount
)
external;
function increaseReservedForCompound(
address _pendleMarket,
uint256[] memory _amounts
)
external;
function pendleChildCompoundInfoReservedForCompound(
address _pendleMarket
)
external
view
returns (uint256[] memory);
function pendleChildCompoundInfoLastIndex(
address _pendleMarket
)
external
view
returns (uint128[] memory);
function pendleChildCompoundInfoRewardTokens(
address _pendleMarket
)
external
view
returns (address[] memory);
function updateRewardTokens(
address _pendleMarket
)
external
returns (bool);
function overWriteIndexAll(
address _pendleMarket
)
external;
function overWriteIndex(
address _pendleMarket,
uint256 _index
)
external;
function overWriteAmounts(
address _pendleMarket
)
external;
}
CallOptionalReturn.sol 39 lines
// SPDX-License-Identifier: -- WISE --
pragma solidity =0.8.25;
import "../InterfaceHub/IERC20.sol";
contract CallOptionalReturn {
/**
* @dev Helper function to do low-level call
*/
function _callOptionalReturn(
address token,
bytes memory data
)
internal
returns (bool call)
{
(
bool success,
bytes memory returndata
) = token.call(
data
);
bool results = returndata.length == 0 || abi.decode(
returndata,
(bool)
);
if (success == false) {
revert();
}
call = success
&& results
&& token.code.length > 0;
}
}
IArbRewardsClaimer.sol 12 lines
// SPDX-License-Identifier: -- WISE --
pragma solidity =0.8.25;
interface IArbRewardsClaimer{
function claim(
address _receiver,
uint256 _accrued,
bytes32[] calldata _proof
)
external;
}
IPendlePowerFarmToken.sol 112 lines
// SPDX-License-Identifier: -- WISE --
pragma solidity =0.8.25;
interface IPendlePowerFarmToken {
function changeGrowthCheckState(
bool _state
)
external;
function changeMinDepositAmount(
uint256 _newMinDepositAmount
)
external;
function changeCompoundRoleState(
address _roleReceiver,
bool _state
)
external;
function changeMintFee(
uint256 _newFee
)
external;
function manualSync()
external;
function addCompoundRewards(
uint256 _amount
)
external;
function withdrawExactShares(
uint256 _shares
)
external
returns (uint256);
function totalLpAssets()
external
view
returns (uint256);
function totalSupply()
external
view
returns (uint256);
function previewUnderlyingLpAssets()
external
view
returns (uint256);
function previewMintShares(
uint256 _underlyingAssetAmount,
uint256 _underlyingLpAssetsCurrent
)
external
view
returns (uint256);
function previewAmountWithdrawShares(
uint256 _shares,
uint256 _underlyingLpAssetsCurrent
)
external
view
returns (uint256);
function previewBurnShares(
uint256 _underlyingAssetAmount,
uint256 _underlyingLpAssetsCurrent
)
external
view
returns (uint256);
function balanceOf(
address _account
)
external
view
returns (uint256);
function withdrawExactAmount(
uint256 _underlyingLpAssetAmount
)
external
returns (uint256);
function depositExactAmount(
uint256 _underlyingLpAssetAmount
)
external
returns (
uint256,
uint256
);
function underlyingLpAssetsCurrent()
external
view
returns (uint256);
function totalLpAssetsToDistribute()
external
view
returns (uint256);
}
IPendlePowerFarmTokenFactory.sol 14 lines
// SPDX-License-Identifier: -- WISE --
pragma solidity =0.8.25;
interface IPendlePowerFarmTokenFactory {
function deploy(
address _underlyingPendleMarket,
string memory _tokenName,
string memory _symbolName,
uint16 _maxCardinality
)
external
returns (address);
}
SimpleERC20Clone.sol 333 lines
// SPDX-License-Identifier: -- WISE --
pragma solidity =0.8.25;
error AllowanceBelowZero();
error ApproveWithZeroAddress();
error BurnExceedsBalance();
error BurnFromZeroAddress();
error InsufficientAllowance();
error MintToZeroAddress();
error TransferAmountExceedsBalance();
error TransferZeroAddress();
contract SimpleERC20 {
string internal _name;
string internal _symbol;
uint8 internal _decimals;
uint256 internal _totalSupply;
mapping(address => uint256) internal _balances;
mapping(address => mapping(address => uint256)) internal _allowances;
// Miscellaneous constants
uint256 internal constant UINT256_MAX = type(uint256).max;
address internal constant ZERO_ADDRESS = address(0);
event Transfer(
address indexed from,
address indexed to,
uint256 value
);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
function name()
external
view
returns (string memory)
{
return _name;
}
function symbol()
external
view
returns (string memory)
{
return _symbol;
}
function decimals()
external
view
returns (uint8)
{
return _decimals;
}
function totalSupply()
public
view
returns (uint256)
{
return _totalSupply;
}
function balanceOf(
address _account
)
public
view
returns (uint256)
{
return _balances[_account];
}
function _transfer(
address _from,
address _to,
uint256 _amount
)
internal
{
if (_from == ZERO_ADDRESS || _to == ZERO_ADDRESS) {
revert TransferZeroAddress();
}
uint256 fromBalance = _balances[_from];
if (fromBalance < _amount) {
revert TransferAmountExceedsBalance();
}
unchecked {
_balances[_from] = fromBalance - _amount;
_balances[_to] += _amount;
}
emit Transfer(
_from,
_to,
_amount
);
}
function _mint(
address _account,
uint256 _amount
)
internal
{
if (_account == ZERO_ADDRESS) {
revert MintToZeroAddress();
}
_totalSupply += _amount;
unchecked {
_balances[_account] += _amount;
}
emit Transfer(
ZERO_ADDRESS,
_account,
_amount
);
}
function _burn(
address _account,
uint256 _amount
)
internal
{
if (_account == ZERO_ADDRESS) {
revert BurnFromZeroAddress();
}
uint256 accountBalance = _balances[
_account
];
if (accountBalance < _amount) {
revert BurnExceedsBalance();
}
unchecked {
_balances[_account] = accountBalance - _amount;
_totalSupply -= _amount;
}
emit Transfer(
_account,
ZERO_ADDRESS,
_amount
);
}
function transfer(
address _to,
uint256 _amount
)
external
returns (bool)
{
_transfer(
_msgSender(),
_to,
_amount
);
return true;
}
function allowance(
address _owner,
address _spender
)
public
view
returns (uint256)
{
return _allowances[_owner][_spender];
}
function approve(
address _spender,
uint256 _amount
)
external
returns (bool)
{
_approve(
_msgSender(),
_spender,
_amount
);
return true;
}
function transferFrom(
address _from,
address _to,
uint256 _amount
)
external
returns (bool)
{
_spendAllowance(
_from,
_msgSender(),
_amount
);
_transfer(
_from,
_to,
_amount
);
return true;
}
function increaseAllowance(
address _spender,
uint256 _addedValue
)
external
returns (bool)
{
address owner = _msgSender();
_approve(
owner,
_spender,
allowance(owner, _spender) + _addedValue
);
return true;
}
function decreaseAllowance(
address _spender,
uint256 _subtractedValue
)
external
returns (bool)
{
address owner = _msgSender();
uint256 currentAllowance = allowance(
owner,
_spender
);
if (currentAllowance < _subtractedValue) {
revert AllowanceBelowZero();
}
unchecked {
_approve(
owner,
_spender,
currentAllowance - _subtractedValue
);
}
return true;
}
function _approve(
address _owner,
address _spender,
uint256 _amount
)
internal
{
if (_owner == ZERO_ADDRESS || _spender == ZERO_ADDRESS) {
revert ApproveWithZeroAddress();
}
_allowances[_owner][_spender] = _amount;
emit Approval(
_owner,
_spender,
_amount
);
}
function _spendAllowance(
address _owner,
address _spender,
uint256 _amount
)
internal
{
uint256 currentAllowance = allowance(
_owner,
_spender
);
if (currentAllowance != UINT256_MAX) {
if (currentAllowance < _amount) {
revert InsufficientAllowance();
}
unchecked {
_approve(
_owner,
_spender,
currentAllowance - _amount
);
}
}
}
function _msgSender()
internal
view
returns (address)
{
return msg.sender;
}
}
PendlePowerFarmToken.sol 800 lines
// SPDX-License-Identifier: -- WISE --
pragma solidity =0.8.25;
import "./SimpleERC20Clone.sol";
import "../../InterfaceHub/IPendle.sol";
import "../../InterfaceHub/IPendleController.sol";
import "../../TransferHub/TransferHelper.sol";
error MarketExpired();
error NotController();
error ZeroFee();
error TooMuchFee();
error NotEnoughLpAssetsTransferred();
error InsufficientShares();
error ZeroAmount();
error FeeTooHigh();
error NotEnoughShares();
error InvalidSharePriceGrowth();
error InvalidSharePrice();
error AlreadyInitialized();
error compoundRoleNotApproved();
error AmountBelowMinDeposit();
contract PendlePowerFarmToken is SimpleERC20, TransferHelper {
// Pendle - LP token address
address public UNDERLYING_PENDLE_MARKET;
address public PENDLE_POWER_FARM_CONTROLLER;
// Total balance of LPs backing at current compound distribution
uint256 public underlyingLpAssetsCurrent;
// Lp assets from compound left to distribute
uint256 public totalLpAssetsToDistribute;
// Interface Object for underlying Market
IPendleMarket public PENDLE_MARKET;
// InterfaceObject for pendle Sy
IPendleSy public PENDLE_SY;
// Interface for Pendle Controller
IPendleController public PENDLE_CONTROLLER;
// sharePrice growth check
bool public growthCheckNecessary;
// Max cardinality of Pendle Market
uint16 public MAX_CARDINALITY;
uint256 public mintFee;
uint256 public lastInteraction;
uint256 private constant ONE_WEEK = 7 days;
uint256 internal constant ONE_YEAR = 365 days;
uint256 private constant MAX_MINT_FEE = 10000;
uint256 private constant PRECISION_FACTOR_E6 = 1E6;
uint256 private constant PRECISION_FACTOR_E18 = 1E18;
uint256 internal constant PRECISION_FACTOR_E36 = PRECISION_FACTOR_E18 * PRECISION_FACTOR_E18;
uint256 internal constant PRECISION_FACTOR_YEAR = PRECISION_FACTOR_E18 * ONE_YEAR;
uint256 MIN_DEPOSIT_AMOUNT = 1E6;
uint256 private INITIAL_TIME_STAMP;
uint256 internal constant RESTRICTION_FACTOR = 10
* PRECISION_FACTOR_E36
/ PRECISION_FACTOR_YEAR;
mapping (address => bool) public compoundRole;
modifier onlyController() {
_onlyController();
_;
}
function _onlyController()
private
view
{
if (msg.sender != PENDLE_POWER_FARM_CONTROLLER) {
revert NotController();
}
}
modifier syncSupply()
{
_triggerIndexUpdate();
_overWriteCheck();
_syncSupply();
_updateRewards();
_setLastInteraction();
_increaseCardinalityNext();
uint256 sharePriceBefore = _getSharePrice();
_;
_validateSharePriceGrowth(
_validateSharePrice(
sharePriceBefore
)
);
}
modifier onlyCompoundRole()
{
_onlyCompoundRole();
_;
}
function _onlyCompoundRole()
private
view
{
if (compoundRole[msg.sender] == false) {
revert compoundRoleNotApproved();
}
}
function _validateSharePrice(
uint256 _sharePriceBefore
)
private
view
returns (uint256)
{
uint256 sharePricenNow = _getSharePrice();
if (sharePricenNow < _sharePriceBefore) {
revert InvalidSharePrice();
}
return sharePricenNow;
}
function changeGrowthCheckState(
bool _state
)
external
onlyController
{
growthCheckNecessary = _state;
}
function _validateSharePriceGrowth(
uint256 _sharePriceNow
)
private
view
{
if (growthCheckNecessary == false) {
return;
}
uint256 timeDifference = block.timestamp
- INITIAL_TIME_STAMP;
uint256 maximum = timeDifference
* RESTRICTION_FACTOR
+ PRECISION_FACTOR_E18;
if (_sharePriceNow > maximum) {
revert InvalidSharePriceGrowth();
}
}
function _overWriteCheck()
internal
{
_wrapOverWrites(
_updateRewardTokens()
);
}
function _triggerIndexUpdate()
internal
{
_withdrawLp(
UNDERLYING_PENDLE_MARKET,
0
);
}
function _wrapOverWrites(
bool _overWritten
)
internal
{
if (_overWritten == true) {
_overWriteIndexAll();
_overWriteAmounts();
}
}
function _updateRewardTokens()
private
returns (bool)
{
return PENDLE_CONTROLLER.updateRewardTokens(
UNDERLYING_PENDLE_MARKET
);
}
function _overWriteIndexAll()
private
{
PENDLE_CONTROLLER.overWriteIndexAll(
UNDERLYING_PENDLE_MARKET
);
}
function _overWriteIndex(
uint256 _index
)
private
{
PENDLE_CONTROLLER.overWriteIndex(
UNDERLYING_PENDLE_MARKET,
_index
);
}
function _overWriteAmounts()
private
{
PENDLE_CONTROLLER.overWriteAmounts(
UNDERLYING_PENDLE_MARKET
);
}
function _updateRewards()
private
{
uint256[] memory rewardsOutsideArray = _calculateRewardsClaimedOutside();
uint256 i;
uint256 l = rewardsOutsideArray.length;
while (i < l) {
if (rewardsOutsideArray[i] > 0) {
PENDLE_CONTROLLER.increaseReservedForCompound(
UNDERLYING_PENDLE_MARKET,
rewardsOutsideArray
);
break;
}
unchecked {
++i;
}
}
}
function _calculateRewardsClaimedOutside()
internal
returns (uint256[] memory)
{
IPendleController PENDLE_CONTROLLER_INSTANCE = PENDLE_CONTROLLER;
address UNDERLYING_PENDLE_MARKET_ADDRESS = UNDERLYING_PENDLE_MARKET;
address[] memory rewardTokens = PENDLE_CONTROLLER_INSTANCE.pendleChildCompoundInfoRewardTokens(
UNDERLYING_PENDLE_MARKET_ADDRESS
);
uint128[] memory lastIndex = PENDLE_CONTROLLER_INSTANCE.pendleChildCompoundInfoLastIndex(
UNDERLYING_PENDLE_MARKET_ADDRESS
);
uint256 l = rewardTokens.length;
uint256[] memory rewardsOutsideArray = new uint256[](l);
uint256 i;
uint128 index;
uint256 activeBalance = _getActiveBalance();
uint256 totalLpAssetsCurrent = totalLpAssets();
uint256 lpBalanceController = _getBalanceLpBalanceController();
address PENDLE_POWER_FARM_CONTROLLER_ADDRESS = PENDLE_POWER_FARM_CONTROLLER;
IPendleMarket PENDLE_MARKET_INSTANCE = PENDLE_MARKET;
while (i < l) {
UserReward memory userReward = _getUserReward(
rewardTokens[i],
PENDLE_POWER_FARM_CONTROLLER_ADDRESS
);
if (userReward.accrued > 0) {
PENDLE_MARKET_INSTANCE.redeemRewards(
PENDLE_POWER_FARM_CONTROLLER_ADDRESS
);
userReward = _getUserReward(
rewardTokens[i],
PENDLE_POWER_FARM_CONTROLLER_ADDRESS
);
}
index = userReward.index;
if (lastIndex[i] == 0 && index > 0) {
rewardsOutsideArray[i] = 0;
_overWriteIndex(
i
);
unchecked {
++i;
}
continue;
}
if (index == lastIndex[i]) {
rewardsOutsideArray[i] = 0;
unchecked {
++i;
}
continue;
}
uint256 indexDiff = index
- lastIndex[i];
bool scaleNecessary = totalLpAssetsCurrent < lpBalanceController;
rewardsOutsideArray[i] = scaleNecessary
? indexDiff
* activeBalance
* totalLpAssetsCurrent
/ lpBalanceController
/ PRECISION_FACTOR_E18
: indexDiff
* activeBalance
/ PRECISION_FACTOR_E18;
_overWriteIndex(
i
);
unchecked {
++i;
}
}
return rewardsOutsideArray;
}
function _getBalanceLpBalanceController()
private
view
returns (uint256)
{
return PENDLE_MARKET.balanceOf(
PENDLE_POWER_FARM_CONTROLLER
);
}
function _getActiveBalance()
private
view
returns (uint256)
{
return PENDLE_MARKET.activeBalance(
PENDLE_POWER_FARM_CONTROLLER
);
}
function _getSharePrice()
private
view
returns (uint256)
{
return previewUnderlyingLpAssets() * PRECISION_FACTOR_E18
/ totalSupply();
}
function _syncSupply()
private
{
uint256 additonalAssets = previewDistribution();
if (additonalAssets == 0) {
return;
}
underlyingLpAssetsCurrent += additonalAssets;
totalLpAssetsToDistribute -= additonalAssets;
}
function _increaseCardinalityNext()
internal
{
MarketStorage memory storageMarket = PENDLE_MARKET._storage();
if (storageMarket.observationCardinalityNext < MAX_CARDINALITY) {
PENDLE_MARKET.increaseObservationsCardinalityNext(
storageMarket.observationCardinalityNext + 1
);
}
}
function _withdrawLp(
address _to,
uint256 _amount
)
internal
{
PENDLE_CONTROLLER.withdrawLp(
UNDERLYING_PENDLE_MARKET,
_to,
_amount
);
}
function _getUserReward(
address _rewardToken,
address _user
)
internal
view
returns (UserReward memory)
{
return PENDLE_MARKET.userReward(
_rewardToken,
_user
);
}
function previewDistribution()
public
view
returns (uint256)
{
uint256 lastInteractioCached = lastInteraction;
if (totalLpAssetsToDistribute == 0) {
return 0;
}
if (block.timestamp == lastInteractioCached) {
return 0;
}
if (totalLpAssetsToDistribute < ONE_WEEK) {
return totalLpAssetsToDistribute;
}
uint256 currentRate = totalLpAssetsToDistribute
/ ONE_WEEK;
uint256 additonalAssets = currentRate
* (block.timestamp - lastInteractioCached);
if (additonalAssets > totalLpAssetsToDistribute) {
return totalLpAssetsToDistribute;
}
return additonalAssets;
}
function _setLastInteraction()
private
{
lastInteraction = block.timestamp;
}
function _applyMintFee(
uint256 _amount
)
internal
view
returns (uint256)
{
return _amount
* (PRECISION_FACTOR_E6 - mintFee)
/ PRECISION_FACTOR_E6;
}
function totalLpAssets()
public
view
returns (uint256)
{
return underlyingLpAssetsCurrent
+ totalLpAssetsToDistribute;
}
function previewUnderlyingLpAssets()
public
view
returns (uint256)
{
return previewDistribution()
+ underlyingLpAssetsCurrent;
}
function previewMintShares(
uint256 _underlyingAssetAmount,
uint256 _underlyingLpAssetsCurrent
)
public
view
returns (uint256)
{
return _underlyingAssetAmount
* totalSupply()
/ _underlyingLpAssetsCurrent;
}
function previewAmountWithdrawShares(
uint256 _shares,
uint256 _underlyingLpAssetsCurrent
)
public
view
returns (uint256)
{
return _shares
* _underlyingLpAssetsCurrent
/ totalSupply();
}
function previewBurnShares(
uint256 _underlyingAssetAmount,
uint256 _underlyingLpAssetsCurrent
)
public
view
returns (uint256)
{
uint256 product = _underlyingAssetAmount
* totalSupply();
return product % _underlyingLpAssetsCurrent == 0
? product / _underlyingLpAssetsCurrent
: product / _underlyingLpAssetsCurrent + 1;
}
function changeCompoundRoleState(
address _compoundRole,
bool _state
)
external
onlyController
{
compoundRole[_compoundRole] = _state;
}
function changeMinDepositAmount(
uint256 _newMinDepositAmount
)
external
onlyController
{
MIN_DEPOSIT_AMOUNT = _newMinDepositAmount;
}
function manualSync()
external
syncSupply
returns (bool)
{
return true;
}
function addCompoundRewards(
uint256 _amount
)
external
syncSupply
onlyCompoundRole
{
if (_amount == 0) {
revert ZeroAmount();
}
totalLpAssetsToDistribute += _amount;
if (msg.sender == PENDLE_POWER_FARM_CONTROLLER) {
return;
}
_safeTransferFrom(
UNDERLYING_PENDLE_MARKET,
msg.sender,
PENDLE_POWER_FARM_CONTROLLER,
_amount
);
}
/**
* @dev External wrapper for mint function.
*/
function depositExactAmount(
uint256 _underlyingLpAssetAmount
)
external
syncSupply
returns (
uint256,
uint256
)
{
if (_underlyingLpAssetAmount < MIN_DEPOSIT_AMOUNT) {
revert AmountBelowMinDeposit();
}
uint256 shares = previewMintShares(
_underlyingLpAssetAmount,
underlyingLpAssetsCurrent
);
if (shares == 0) {
revert NotEnoughLpAssetsTransferred();
}
uint256 reducedShares = _applyMintFee(
shares
);
uint256 feeShares = shares
- reducedShares;
if (feeShares == 0) {
revert ZeroFee();
}
if (reducedShares == feeShares) {
revert TooMuchFee();
}
_mint(
msg.sender,
reducedShares
);
_mint(
PENDLE_POWER_FARM_CONTROLLER,
feeShares
);
underlyingLpAssetsCurrent += _underlyingLpAssetAmount;
_safeTransferFrom(
UNDERLYING_PENDLE_MARKET,
msg.sender,
PENDLE_POWER_FARM_CONTROLLER,
_underlyingLpAssetAmount
);
return (
reducedShares,
feeShares
);
}
function changeMintFee(
uint256 _newFee
)
external
onlyController
{
if (_newFee > MAX_MINT_FEE) {
revert FeeTooHigh();
}
mintFee = _newFee;
}
/**
* @dev External wrapper for burn function.
*/
function withdrawExactShares(
uint256 _shares
)
external
syncSupply
returns (uint256)
{
if (_shares == 0) {
revert ZeroAmount();
}
if (_shares > balanceOf(msg.sender)) {
revert InsufficientShares();
}
uint256 tokenAmount = previewAmountWithdrawShares(
_shares,
underlyingLpAssetsCurrent
);
underlyingLpAssetsCurrent -= tokenAmount;
_burn(
msg.sender,
_shares
);
if (msg.sender == PENDLE_POWER_FARM_CONTROLLER) {
return tokenAmount;
}
_withdrawLp(
msg.sender,
tokenAmount
);
return tokenAmount;
}
function withdrawExactAmount(
uint256 _underlyingLpAssetAmount
)
external
syncSupply
returns (uint256)
{
if (_underlyingLpAssetAmount == 0) {
revert ZeroAmount();
}
uint256 shares = previewBurnShares(
_underlyingLpAssetAmount,
underlyingLpAssetsCurrent
);
if (shares > balanceOf(msg.sender)) {
revert NotEnoughShares();
}
_burn(
msg.sender,
shares
);
underlyingLpAssetsCurrent -= _underlyingLpAssetAmount;
_withdrawLp(
msg.sender,
_underlyingLpAssetAmount
);
return shares;
}
function initialize(
address _underlyingPendleMarket,
address _pendleController,
string memory _tokenName,
string memory _symbolName,
uint16 _maxCardinality
)
external
{
if (address(PENDLE_MARKET) != address(0)) {
revert AlreadyInitialized();
}
growthCheckNecessary = true;
PENDLE_MARKET = IPendleMarket(
_underlyingPendleMarket
);
if (PENDLE_MARKET.isExpired() == true) {
revert MarketExpired();
}
PENDLE_CONTROLLER = IPendleController(
_pendleController
);
MAX_CARDINALITY = _maxCardinality;
_name = _tokenName;
_symbol = _symbolName;
PENDLE_POWER_FARM_CONTROLLER = _pendleController;
UNDERLYING_PENDLE_MARKET = _underlyingPendleMarket;
(
address pendleSyAddress,
,
) = PENDLE_MARKET.readTokens();
PENDLE_SY = IPendleSy(
pendleSyAddress
);
_decimals = PENDLE_SY.decimals();
lastInteraction = block.timestamp;
_totalSupply = 1;
underlyingLpAssetsCurrent = 1;
mintFee = 3000;
INITIAL_TIME_STAMP = block.timestamp;
}
}
PendlePowerFarmController.sol 810 lines
// SPDX-License-Identifier: -- WISE --
pragma solidity =0.8.25;
import "./PendlePowerFarmTokenFactory.sol";
import "./PendlePowerFarmControllerHelper.sol";
contract PendlePowerFarmController is PendlePowerFarmControllerHelper {
PendlePowerFarmTokenFactory public immutable PENDLE_POWER_FARM_TOKEN_FACTORY;
constructor(
address _vePendle,
address _pendleToken,
address _voterContract,
address _voterRewardsClaimerAddress,
address _wiseOracleHub
)
PendlePowerFarmControllerBase(
_vePendle,
_pendleToken,
_voterContract,
_voterRewardsClaimerAddress,
_wiseOracleHub
)
{
PENDLE_POWER_FARM_TOKEN_FACTORY = new PendlePowerFarmTokenFactory(
address(this)
);
}
function withdrawLp(
address _pendleMarket,
address _to,
uint256 _amount
)
external
onlyChildContract(_pendleMarket)
{
_safeTransfer(
_pendleMarket,
_to,
_amount
);
emit WithdrawLp(
_pendleMarket,
_to,
_amount
);
}
function exchangeRewardsForCompoundingWithIncentive(
address _pendleMarket,
address _rewardToken,
uint256 _rewardAmount
)
external
syncSupply(_pendleMarket)
returns (uint256)
{
CompoundStruct memory childInfo = pendleChildCompoundInfo[
_pendleMarket
];
uint256 index = _findIndex(
childInfo.rewardTokens,
_rewardToken
);
if (childInfo.reservedForCompound[index] < _rewardAmount) {
revert NotEnoughCompound();
}
uint256 sendingAmount = _getAmountToSend(
_pendleMarket,
_getTokensInETH(
_rewardToken,
_rewardAmount
)
);
childInfo.reservedForCompound[index] -= _rewardAmount;
pendleChildCompoundInfo[_pendleMarket] = childInfo;
_safeTransferFrom(
_pendleMarket,
msg.sender,
address(this),
sendingAmount
);
IPendlePowerFarmToken(pendleChildAddress[_pendleMarket]).addCompoundRewards(
sendingAmount
);
_safeTransfer(
childInfo.rewardTokens[index],
msg.sender,
_rewardAmount
);
emit ExchangeRewardsForCompounding(
_pendleMarket,
_rewardToken,
_rewardAmount,
sendingAmount
);
return sendingAmount;
}
function exchangeLpFeesForPendleWithIncentive(
address _pendleMarket,
uint256 _pendleChildShares
)
external
syncSupply(_pendleMarket)
returns (
uint256,
uint256
)
{
if (_pendleChildShares == 0) {
revert ZeroShares();
}
address pendleChild = pendleChildAddress[
_pendleMarket
];
uint256 tokenAmountSend = _getAmountToSend(
PENDLE_TOKEN_ADDRESS,
_getTokensInETH(
pendleChild,
_pendleChildShares
)
);
reservedPendleForLocking += tokenAmountSend;
_safeTransferFrom(
PENDLE_TOKEN_ADDRESS,
msg.sender,
address(this),
tokenAmountSend
);
uint256 withdrawnAmount = IPendlePowerFarmToken(pendleChild).withdrawExactShares(
_pendleChildShares
);
_safeTransfer(
_pendleMarket,
msg.sender,
withdrawnAmount
);
emit ExchangeLpFeesForPendle(
_pendleMarket,
_pendleChildShares,
tokenAmountSend,
withdrawnAmount
);
return(
tokenAmountSend,
withdrawnAmount
);
}
function skim(
address _pendleMarket
)
external
returns (uint256)
{
address childMarket = pendleChildAddress[
_pendleMarket
];
if (childMarket == ZERO_ADDRESS) {
revert WrongAddress();
}
uint256 balance = IPendleMarket(_pendleMarket).balanceOf(
address(this)
);
uint256 totalAssets = IPendlePowerFarmToken(
childMarket
).totalLpAssets();
if (balance < totalAssets + 1) {
revert NothingToSkim();
}
uint256 difference = balance
- totalAssets
+ 1;
_safeTransfer(
_pendleMarket,
master,
difference
);
return difference;
}
function changeCompoundRoleState(
address _pendleMarket,
address _roleReceiver,
bool _state
)
public
onlyMaster
{
address pendleChild = pendleChildAddress[
_pendleMarket
];
if (pendleChild == ZERO_ADDRESS) {
revert WrongAddress();
}
IPendlePowerFarmToken(pendleChild).changeCompoundRoleState(
_roleReceiver,
_state
);
}
function changeMinDepositAmount(
address _pendleMarket,
uint256 _newAmount
)
external
onlyMaster
{
address pendleChild = pendleChildAddress[
_pendleMarket
];
if (pendleChild == ZERO_ADDRESS) {
revert WrongAddress();
}
IPendlePowerFarmToken(pendleChild).changeMinDepositAmount(
_newAmount
);
}
function claimAirdropSafe(
bytes[] memory _calldataArray,
address[] memory _contractAddresses
)
external
onlyMaster
{
uint256 callDataLength = _calldataArray.length;
if (callDataLength != _contractAddresses.length) {
revert InvalidLength();
}
bytes32 initialHashChainResult = _getHashChainResult();
uint256 i;
address currentAddress;
while (i < callDataLength) {
currentAddress = _contractAddresses[i];
if (currentAddress == ZERO_ADDRESS) {
revert ZeroAddress();
}
if (currentAddress == address(this)) {
revert SelfCallNotAllowed();
}
if (_calldataArray[i].length < 4) {
revert CallDataTooShort(i);
}
if (_forbiddenSelector(_calldataArray[i]) == true) {
revert ForbiddenSelector();
}
(
bool success
,
) = currentAddress.call(
_calldataArray[i]
);
if (success == false) {
revert AirdropFailed();
}
unchecked {
++i;
}
}
if (_getHashChainResult() != initialHashChainResult) {
revert HashChainManipulated();
}
}
function addPendleMarket(
address _pendleMarket,
string memory _tokenName,
string memory _symbolName,
uint16 _maxCardinality
)
external
onlyMaster
{
if (pendleChildAddress[_pendleMarket] > ZERO_ADDRESS) {
revert AlreadySet();
}
if (activePendleMarketsLength() == MAX_PENDLE_MARKETS) {
revert MaxPendleMarketsReached();
}
if (_pendleMarket == ZERO_ADDRESS) {
revert WrongAddress();
}
address pendleChild = PENDLE_POWER_FARM_TOKEN_FACTORY.deploy(
_pendleMarket,
_tokenName,
_symbolName,
_maxCardinality
);
pendleChildAddress[_pendleMarket] = pendleChild;
_setRewardTokens(
_pendleMarket,
_getRewardTokens(
_pendleMarket
)
);
CompoundStruct storage childInfo = pendleChildCompoundInfo[
_pendleMarket
];
uint256 rewardTokensLength = childInfo
.rewardTokens
.length;
childInfo.lastIndex = new uint128[](
rewardTokensLength
);
childInfo.reservedForCompound = new uint256[](
rewardTokensLength
);
uint256 i;
while (i < rewardTokensLength) {
address token = childInfo.rewardTokens[i];
childInfo.lastIndex[i] = _getUserRewardIndex(
_pendleMarket,
token,
address(this)
);
childInfo.reservedForCompound[i] = 0;
_checkFeed(
token
);
unchecked {
++i;
}
}
_checkFeed(
_pendleMarket
);
activePendleMarkets.push(
_pendleMarket
);
changeCompoundRoleState({
_pendleMarket: _pendleMarket,
_roleReceiver: address(this),
_state: true
});
emit AddPendleMarket(
_pendleMarket,
pendleChild
);
}
function updateRewardTokens(
address _pendleMarket
)
external
onlyChildContract(_pendleMarket)
returns (bool)
{
address[] memory rewardTokens = _getRewardTokens(
_pendleMarket
);
if (_compareHashes(_pendleMarket, rewardTokens) == true) {
return false;
}
_setRewardTokens(
_pendleMarket,
rewardTokens
);
emit UpdateRewardTokens(
_pendleMarket,
rewardTokens
);
return true;
}
function changeExchangeIncentive(
uint256 _newExchangeIncentive
)
external
onlyMaster
{
exchangeIncentive = _newExchangeIncentive;
emit ChangeExchangeIncentive(
_newExchangeIncentive
);
}
function changeSyncCheck(
address _pendleMarket,
bool _state
)
external
onlyMaster
{
address child = _checkChildExistence(
_pendleMarket
);
syncNotNecessary[child] = _state;
}
function changeGrowthCheckState(
address _pendleMarket,
bool _state
)
external
onlyMaster
{
address child = _checkChildExistence(
_pendleMarket
);
IPendlePowerFarmToken(
child
).changeGrowthCheckState(
_state
);
}
function changeMintFee(
address _pendleMarket,
uint256 _newFee
)
external
onlyMaster
{
address child = _checkChildExistence(
_pendleMarket
);
IPendlePowerFarmToken(
child
).changeMintFee(
_newFee
);
emit ChangeMintFee(
_pendleMarket,
_newFee
);
}
function _checkChildExistence(
address _pendleMarket
)
private
view
returns (address child)
{
child = pendleChildAddress[
_pendleMarket
];
if (child == ZERO_ADDRESS) {
revert WrongAddress();
}
}
/**
* @dev Can also be used to extend existing lock.
*/
function lockPendle(
uint256 _amount,
uint128 _weeks,
bool _fromInside,
bool _sameExpiry
)
external
onlyMaster
returns (uint256 newVeBalance)
{
syncAllSupply();
uint256 currentExpiry = _getExpiry();
uint128 expiry = _sameExpiry
? uint128(currentExpiry)
: _calcExpiry(
_weeks
);
if (uint256(expiry) < currentExpiry) {
revert LockTimeTooShort();
}
if (_amount > 0) {
_safeApprove(
PENDLE_TOKEN_ADDRESS,
VE_PENDLE_CONTRACT_ADDRESS,
_amount
);
if (_fromInside == false) {
_safeTransferFrom(
PENDLE_TOKEN_ADDRESS,
msg.sender,
address(this),
_amount
);
}
}
newVeBalance = PENDLE_LOCK.increaseLockPosition(
uint128(_amount),
expiry
);
syncAllSupply();
if (_fromInside == false) {
return newVeBalance;
}
if (_amount > 0) {
reservedPendleForLocking -= _amount;
}
emit LockPendle(
_amount,
expiry,
newVeBalance,
_fromInside,
_sameExpiry,
block.timestamp
);
}
function claimArb(
uint256 _accrued,
bytes32[] calldata _proof
)
external
onlyArbitrum
{
ARB_REWARDS.claim(
master,
_accrued,
_proof
);
emit ClaimArb(
_accrued,
_proof,
block.timestamp
);
}
function withdrawLock()
external
onlyMaster
returns (uint256 amount)
{
if (IS_ETH_MAIN == false) {
amount = reservedPendleForLocking;
reservedPendleForLocking = 0;
_safeTransfer(
PENDLE_TOKEN_ADDRESS,
master,
amount
);
emit WithdrawLock(
amount,
block.timestamp
);
return amount;
}
if (_getExpiry() > block.timestamp) {
revert NotExpired();
}
syncAllSupply();
amount = PENDLE_LOCK.withdraw();
_safeTransfer(
PENDLE_TOKEN_ADDRESS,
master,
amount
);
syncAllSupply();
emit WithdrawLock(
amount,
block.timestamp
);
}
function increaseReservedForCompound(
address _pendleMarket,
uint256[] calldata _amounts
)
external
onlyChildContract(_pendleMarket)
{
CompoundStruct memory childInfo = pendleChildCompoundInfo[
_pendleMarket
];
uint256 i;
uint256 length = childInfo.rewardTokens.length;
while (i < length) {
childInfo.reservedForCompound[i] += _amounts[i];
unchecked {
++i;
}
}
pendleChildCompoundInfo[_pendleMarket] = childInfo;
emit IncreaseReservedForCompound(
_pendleMarket,
_amounts
);
}
function overWriteIndex(
address _pendleMarket,
uint256 _tokenIndex
)
public
onlyChildContract(_pendleMarket)
{
CompoundStruct storage childInfo = pendleChildCompoundInfo[
_pendleMarket
];
childInfo.lastIndex[_tokenIndex] = _getUserRewardIndex(
_pendleMarket,
childInfo.rewardTokens[_tokenIndex],
address(this)
);
}
function overWriteIndexAll(
address _pendleMarket
)
external
onlyChildContract(_pendleMarket)
{
uint256 i;
uint256 length = pendleChildCompoundInfo[
_pendleMarket
].rewardTokens.length;
while (i < length) {
overWriteIndex(
_pendleMarket,
i
);
unchecked {
++i;
}
}
}
function overWriteAmounts(
address _pendleMarket
)
external
onlyChildContract(_pendleMarket)
{
CompoundStruct storage childInfo = pendleChildCompoundInfo[
_pendleMarket
];
childInfo.reservedForCompound = new uint256[](
childInfo.rewardTokens.length
);
}
function claimVoteRewards(
uint256 _amount,
bytes32[] calldata _merkleProof
)
external
{
PENDLE_VOTE_REWARDS.claimRetail(
address(this),
_amount,
_merkleProof
);
emit ClaimVoteRewards(
_amount,
_merkleProof,
block.timestamp
);
}
function forwardETH(
address _to,
uint256 _amount
)
public
onlyMaster
{
if (sendingProgress == true) {
revert CheckSendingOnGoing();
}
_sendValue(
_to,
_amount
);
sendingProgress = false;
}
function vote(
address[] calldata _pools,
uint64[] calldata _weights
)
external
onlyMaster
{
if (_weights.length != _pools.length) {
revert InvalidLength();
}
uint256 i;
uint256 len = _weights.length;
uint256 weightSum;
while (i < len) {
unchecked {
weightSum += _weights[i];
++i;
}
}
if (weightSum > PRECISION_FACTOR_E18) {
revert InvalidWeightSum();
}
PENDLE_VOTER.vote(
_pools,
_weights
);
}
}
PendlePowerFarmTokenFactory.sol 110 lines
// SPDX-License-Identifier: -- WISE --
pragma solidity =0.8.25;
import "./PendlePowerFarmToken.sol";
error DeployForbidden();
contract PendlePowerFarmTokenFactory {
address internal constant ZERO_ADDRESS = address(0x0);
address public immutable IMPLEMENTATION_TARGET;
address public immutable PENDLE_POWER_FARM_CONTROLLER;
constructor(
address _pendlePowerFarmController
)
{
PENDLE_POWER_FARM_CONTROLLER = _pendlePowerFarmController;
PendlePowerFarmToken implementation = new PendlePowerFarmToken{
salt: keccak256(
abi.encodePacked(
_pendlePowerFarmController
)
)
}();
IMPLEMENTATION_TARGET = address(
implementation
);
}
function deploy(
address _underlyingPendleMarket,
string memory _tokenName,
string memory _symbolName,
uint16 _maxCardinality
)
external
returns (address)
{
if (msg.sender != PENDLE_POWER_FARM_CONTROLLER) {
revert DeployForbidden();
}
return _clone(
_underlyingPendleMarket,
_tokenName,
_symbolName,
_maxCardinality
);
}
function _clone(
address _underlyingPendleMarket,
string memory _tokenName,
string memory _symbolName,
uint16 _maxCardinality
)
private
returns (address pendlePowerFarmTokenAddress)
{
bytes32 salt = keccak256(
abi.encodePacked(
_underlyingPendleMarket
)
);
bytes20 targetBytes = bytes20(
IMPLEMENTATION_TARGET
);
assembly {
let clone := mload(0x40)
mstore(
clone,
0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000
)
mstore(
add(clone, 0x14),
targetBytes
)
mstore(
add(clone, 0x28),
0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000
)
pendlePowerFarmTokenAddress := create2(
0,
clone,
0x37,
salt
)
}
PendlePowerFarmToken(pendlePowerFarmTokenAddress).initialize(
_underlyingPendleMarket,
PENDLE_POWER_FARM_CONTROLLER,
_tokenName,
_symbolName,
_maxCardinality
);
}
}
PendlePowerFarmControllerBase.sol 346 lines
// SPDX-License-Identifier: -- WISE --
pragma solidity =0.8.25;
import "../../OwnableMaster.sol";
import "../../TransferHub/TransferHelper.sol";
import "../../TransferHub/ApprovalHelper.sol";
import "../../TransferHub/SendValueHelper.sol";
import "../../InterfaceHub/IPendle.sol";
import "../../InterfaceHub/IArbRewardsClaimer.sol";
import "../../InterfaceHub/IWiseOracleHub.sol";
import "../../InterfaceHub/IPendlePowerFarmToken.sol";
import "../../InterfaceHub/IPendlePowerFarmTokenFactory.sol";
error NotAllowed();
error AlreadySet();
error NotExpired();
error LockTimeTooShort();
error ZeroShares();
error ValueTooSmall();
error InvalidLength();
error InvalidWeightSum();
error ZeroAddress();
error SelfCallNotAllowed();
error NothingToSkim();
error NotFound();
error NotEnoughCompound();
error NotArbitrum();
error CheckSendingOnGoing();
error MaxPendleMarketsReached();
error AirdropFailed();
error HashChainManipulated();
error ForbiddenSelector();
error WrongAddress();
error CallDataTooShort(uint256);
contract PendlePowerFarmControllerBase is
OwnableMaster,
TransferHelper,
ApprovalHelper,
SendValueHelper
{
struct CompoundStruct {
uint256[] reservedForCompound;
uint128[] lastIndex;
address[] rewardTokens;
}
address internal immutable PENDLE_TOKEN_ADDRESS;
address internal immutable VOTER_CONTRACT_ADDRESS;
address internal immutable VOTER_REWARDS_CLAIMER_ADDRESS;
address internal immutable WISE_ORACLE_HUB_ADDRESS;
address internal immutable VE_PENDLE_CONTRACT_ADDRESS;
uint256 internal constant PRECISION_FACTOR_E6 = 1E6;
uint256 internal constant PRECISION_FACTOR_E10 = 1E10;
uint256 internal constant PRECISION_FACTOR_E18 = 1E18;
uint256 internal constant MAINNET_CHAIN_ID = 1;
uint256 internal constant ARBITRUM_CHAIN_ID = 42161;
uint256 public reservedPendleForLocking;
mapping(address => address) public pendleChildAddress;
mapping(address => CompoundStruct) pendleChildCompoundInfo;
mapping(address => bool) public syncNotNecessary;
address[] public activePendleMarkets;
bool immutable IS_ETH_MAIN;
uint128 internal constant WEEK = 7 days;
uint256 public exchangeIncentive;
uint256 internal constant MAX_PENDLE_MARKETS = 42;
IPendleLock immutable public PENDLE_LOCK;
IPendleVoter immutable public PENDLE_VOTER;
IPendleVoteRewards immutable public PENDLE_VOTE_REWARDS;
IArbRewardsClaimer public ARB_REWARDS;
address internal constant ARB_REWARDS_ADDRESS = 0x23a102e78D1FF1645a3666691495174764a5FCAF;
address internal constant ARB_TOKEN_ADDRESS = 0x912CE59144191C1204E64559FE8253a0e49E6548;
IWiseOracleHub immutable internal ORACLE_HUB;
bytes4 internal constant APPROVE_SELECTOR = 0x095ea7b3;
bytes4 internal constant PERMIT_SELECTOR = 0xd505accf;
bytes32 internal constant INITIAL_HASH = keccak256(
abi.encodePacked(ZERO_ADDRESS, uint256(0))
);
IERC20 immutable PENDLE_TOKEN_INSTANCE;
constructor(
address _vePendle,
address _pendleToken,
address _voterContract,
address _voterRewardsClaimerAddress,
address _wiseOracleHub
)
OwnableMaster(
msg.sender
)
{
IS_ETH_MAIN = block.chainid == MAINNET_CHAIN_ID
? true
: false;
PENDLE_TOKEN_ADDRESS = _pendleToken;
PENDLE_TOKEN_INSTANCE = IERC20(
_pendleToken
);
VOTER_CONTRACT_ADDRESS = _voterContract;
VOTER_REWARDS_CLAIMER_ADDRESS = _voterRewardsClaimerAddress;
WISE_ORACLE_HUB_ADDRESS = _wiseOracleHub;
VE_PENDLE_CONTRACT_ADDRESS = _vePendle;
PENDLE_LOCK = IPendleLock(
_vePendle
);
PENDLE_VOTER = IPendleVoter(
_voterContract
);
PENDLE_VOTE_REWARDS = IPendleVoteRewards(
_voterRewardsClaimerAddress
);
ORACLE_HUB = IWiseOracleHub(
_wiseOracleHub
);
ARB_REWARDS = IArbRewardsClaimer(
ARB_REWARDS_ADDRESS
);
exchangeIncentive = 50000;
}
receive()
external
payable
{
_checkReentrancy();
emit ETHReceived(
msg.value,
msg.sender
);
}
event ETHReceived(
uint256 _amount,
address _sender
);
event ChangeExchangeIncentive(
uint256 _newExchangeIncentive
);
event WithdrawLp(
address indexed _pendleMarket,
address indexed _to,
uint256 _amount
);
event ExchangeRewardsForCompounding(
address indexed _pendleMarket,
address indexed _rewardToken,
uint256 _rewardAmount,
uint256 _sendingAmount
);
event ExchangeLpFeesForPendle(
address indexed _pendleMarket,
uint256 _pendleChildShares,
uint256 _tokenAmountSend,
uint256 _withdrawnAmount
);
event AddPendleMarket(
address indexed _pendleMarket,
address indexed _pendleChildAddress
);
event UpdateRewardTokens(
address indexed _pendleMarket,
address[] _rewardTokens
);
event ChangeMintFee(
address indexed _pendleMarket,
uint256 _newFee
);
event LockPendle(
uint256 _amount,
uint128 _expiry,
uint256 _newVeBalance,
bool _fromInside,
bool _sameExpiry,
uint256 _timestamp
);
event ClaimArb(
uint256 _accrued,
bytes32[] _proof,
uint256 _timestamp
);
event IncreaseReservedForCompound(
address indexed _pendleMarket,
uint256[] _amounts
);
event ClaimVoteRewards(
uint256 _amount,
bytes32[] _merkleProof,
uint256 _timestamp
);
event WithdrawLock(
uint256 _amount,
uint256 _timestamp
);
modifier syncSupply(
address _pendleMarket
)
{
_syncSupply(
_pendleMarket
);
_;
}
modifier onlyChildContract(
address _pendleMarket
)
{
_onlyChildContract(
_pendleMarket
);
_;
}
modifier onlyArbitrum()
{
_onlyArbitrum();
_;
}
function _onlyArbitrum()
private
view
{
if (block.chainid != ARBITRUM_CHAIN_ID) {
revert NotArbitrum();
}
}
function _onlyChildContract(
address _pendleMarket
)
private
view
{
if (msg.sender != pendleChildAddress[_pendleMarket]) {
revert NotAllowed();
}
}
function _syncSupply(
address _pendleMarket
)
internal
{
address child = pendleChildAddress[
_pendleMarket
];
if (child == ZERO_ADDRESS) {
revert WrongAddress();
}
IPendlePowerFarmToken(child).manualSync();
}
function syncAllSupply()
public
{
uint256 i;
uint256 length = activePendleMarkets.length;
while (i < length) {
address pendleMarket = activePendleMarkets[i];
unchecked {
++i;
}
if (_checkSyncNotNecessary(pendleMarket) == true) {
continue;
}
_syncSupply(
pendleMarket
);
}
}
function _checkSyncNotNecessary(
address _pendleMarket
)
private
view
returns (bool)
{
address child = pendleChildAddress[
_pendleMarket
];
return syncNotNecessary[child] == true;
}
function _checkReentrancy()
internal
view
{
if (sendingProgress == true) {
revert CheckSendingOnGoing();
}
}
}
PendlePowerFarmControllerHelper.sol 377 lines
// SPDX-License-Identifier: -- WISE --
pragma solidity =0.8.25;
import "./PendlePowerFarmControllerBase.sol";
abstract contract PendlePowerFarmControllerHelper is PendlePowerFarmControllerBase {
function _findIndex(
address[] memory _array,
address _value
)
internal
pure
returns (uint256)
{
uint256 i;
uint256 len = _array.length;
while (i < len) {
if (_array[i] == _value) {
return i;
}
unchecked {
++i;
}
}
revert NotFound();
}
function _calcExpiry(
uint128 _weeks
)
internal
view
returns (uint128)
{
uint128 startTime = uint128(
(block.timestamp / WEEK) * WEEK
);
return startTime + (_weeks * WEEK);
}
function _getExpiry()
internal
view
returns (uint256)
{
return _getPositionData(address(this)).expiry;
}
function _getLockAmount()
internal
view
returns (uint256)
{
return _getPositionData(address(this)).amount;
}
function _getPositionData(
address _user
)
private
view
returns (LockedPosition memory)
{
return PENDLE_LOCK.positionData(
_user
);
}
function _getAmountToSend(
address _tokenAddress,
uint256 _rewardValue
)
internal
view
returns (uint256)
{
uint256 sendingValue = _rewardValue
* (PRECISION_FACTOR_E6 - exchangeIncentive)
/ PRECISION_FACTOR_E6;
if (sendingValue < PRECISION_FACTOR_E10) {
revert ValueTooSmall();
}
return _getTokensFromETH(
_tokenAddress,
sendingValue
);
}
function pendleChildCompoundInfoReservedForCompound(
address _pendleMarket
)
external
view
returns (uint256[] memory)
{
return pendleChildCompoundInfo[_pendleMarket].reservedForCompound;
}
function pendleChildCompoundInfoLastIndex(
address _pendleMarket
)
external
view
returns (uint128[] memory)
{
return pendleChildCompoundInfo[_pendleMarket].lastIndex;
}
function pendleChildCompoundInfoRewardTokens(
address _pendleMarket
)
external
view
returns (address[] memory)
{
return pendleChildCompoundInfo[_pendleMarket].rewardTokens;
}
function activePendleMarketsLength()
public
view
returns (uint256)
{
return activePendleMarkets.length;
}
function _checkFeed(
address token
)
internal
view
{
if (ORACLE_HUB.priceFeed(token) == ZERO_ADDRESS) {
revert WrongAddress();
}
}
function _getRewardTokens(
address _pendleMarket
)
internal
view
returns (address[] memory)
{
return IPendleMarket(
_pendleMarket
).getRewardTokens();
}
function _getUserReward(
address _pendleMarket,
address _rewardToken,
address _user
)
internal
view
returns (UserReward memory)
{
return IPendleMarket(
_pendleMarket
).userReward(
_rewardToken,
_user
);
}
function _getUserRewardIndex(
address _pendleMarket,
address _rewardToken,
address _user
)
internal
view
returns (uint128)
{
return _getUserReward(
_pendleMarket,
_rewardToken,
_user
).index;
}
function _getTokensInETH(
address _tokenAddress,
uint256 _tokenAmount
)
internal
view
returns (uint256)
{
return ORACLE_HUB.getTokensInETH(
_tokenAddress,
_tokenAmount
);
}
function _getTokensFromETH(
address _tokenAddress,
uint256 _ethValue
)
internal
view
returns (uint256)
{
return ORACLE_HUB.getTokensFromETH(
_tokenAddress,
_ethValue
);
}
function _compareHashes(
address _pendleMarket,
address[] memory rewardTokensToCompare
)
internal
view
returns (bool)
{
return keccak256(
abi.encode(
rewardTokensToCompare
)
) == keccak256(
abi.encode(
pendleChildCompoundInfo[_pendleMarket].rewardTokens
)
);
}
function _forbiddenSelector(
bytes memory _callData
)
internal
pure
returns (bool forbidden)
{
bytes4 selector;
assembly {
selector := mload(add(_callData, 32))
}
if (selector == APPROVE_SELECTOR) {
return true;
}
if (selector == PERMIT_SELECTOR) {
return true;
}
}
function _getHashChainResult()
internal
view
returns (bytes32)
{
uint256 pendleTokenBalance = PENDLE_TOKEN_INSTANCE.balanceOf(
address(this)
);
bytes32 floatingHash = keccak256(
abi.encodePacked(
INITIAL_HASH,
pendleTokenBalance
)
);
uint256 i;
address currentMarket;
uint256 marketLength = activePendleMarkets.length;
while (i < marketLength) {
currentMarket = activePendleMarkets[i];
floatingHash = _getRewardTokenHashes(
currentMarket,
floatingHash
);
floatingHash = _encodeFloatingHash(
floatingHash,
currentMarket
);
unchecked{
++i;
}
}
return floatingHash;
}
function _encodeFloatingHash(
bytes32 _floatingHash,
address _currentMarket
)
internal
view
returns (bytes32)
{
return keccak256(
abi.encodePacked(
_floatingHash,
IERC20(_currentMarket).balanceOf(
address(this)
)
)
);
}
function _getRewardTokenHashes(
address _pendleMarket,
bytes32 _floatingHash
)
internal
view
returns (bytes32)
{
address[] memory rewardTokens = pendleChildCompoundInfo[_pendleMarket].rewardTokens;
uint256 l = rewardTokens.length;
uint256 i = 0;
while (i < l) {
if (rewardTokens[i] == PENDLE_TOKEN_ADDRESS) {
unchecked{
++i;
}
continue;
}
_floatingHash = _encodeFloatingHash(
_floatingHash,
rewardTokens[i]
);
unchecked{
++i;
}
}
return _floatingHash;
}
function _setRewardTokens(
address _pendleMarket,
address[] memory _rewardTokens
)
internal
{
pendleChildCompoundInfo[_pendleMarket].rewardTokens = _rewardTokens;
}
function getExpiry()
external
view
returns (uint256)
{
return _getExpiry();
}
function getLockAmount()
external
view
returns (uint256)
{
return _getLockAmount();
}
}
Read Contract
ARB_REWARDS 0x765d8b2e → address
PENDLE_LOCK 0xfcbc1d60 → address
PENDLE_POWER_FARM_TOKEN_FACTORY 0x98ae1f52 → address
PENDLE_VOTER 0x170c95b7 → address
PENDLE_VOTE_REWARDS 0x80ae2e5c → address
activePendleMarkets 0xd850e319 → address
activePendleMarketsLength 0xd682e30a → uint256
exchangeIncentive 0x8d8f3730 → uint256
getExpiry 0xf61c266b → uint256
getLockAmount 0xd64c34fc → uint256
master 0xee97f7f3 → address
pendleChildAddress 0x241d8afe → address
pendleChildCompoundInfoLastIndex 0x66b2d8f9 → uint128[]
pendleChildCompoundInfoReservedForCompound 0xf2bf69f6 → uint256[]
pendleChildCompoundInfoRewardTokens 0x10d2b492 → address[]
proposedMaster 0xd3573a33 → address
reservedPendleForLocking 0xd5ca7970 → uint256
sendingProgress 0x019dbb63 → bool
syncNotNecessary 0x9fc49734 → bool
Write Contract 27 functions
These functions modify contract state and require a wallet transaction to execute.
addPendleMarket 0x7afcdc3c
address _pendleMarket
string _tokenName
string _symbolName
uint16 _maxCardinality
changeCompoundRoleState 0xcaf44bd6
address _pendleMarket
address _roleReceiver
bool _state
changeExchangeIncentive 0x438e55a0
uint256 _newExchangeIncentive
changeGrowthCheckState 0x3684a72b
address _pendleMarket
bool _state
changeMinDepositAmount 0x17f8abb0
address _pendleMarket
uint256 _newAmount
changeMintFee 0xc8a7caac
address _pendleMarket
uint256 _newFee
changeSyncCheck 0x9c823f37
address _pendleMarket
bool _state
claimAirdropSafe 0xe3b9bac8
bytes[] _calldataArray
address[] _contractAddresses
claimArb 0x00445e4b
uint256 _accrued
bytes32[] _proof
claimOwnership 0x4e71e0c8
No parameters
claimVoteRewards 0x6109cdbf
uint256 _amount
bytes32[] _merkleProof
exchangeLpFeesForPendleWithIncentive 0x6797d24c
address _pendleMarket
uint256 _pendleChildShares
returns: uint256, uint256
exchangeRewardsForCompoundingWithIncentive 0x78b7d455
address _pendleMarket
address _rewardToken
uint256 _rewardAmount
returns: uint256
forwardETH 0xdf61427e
address _to
uint256 _amount
increaseReservedForCompound 0x7aeaa75d
address _pendleMarket
uint256[] _amounts
lockPendle 0x3f6f34de
uint256 _amount
uint128 _weeks
bool _fromInside
bool _sameExpiry
returns: uint256
overWriteAmounts 0x5d99ba83
address _pendleMarket
overWriteIndex 0x04b473bd
address _pendleMarket
uint256 _tokenIndex
overWriteIndexAll 0x3f828600
address _pendleMarket
proposeOwner 0xb5ed298a
address _proposedOwner
renounceOwnership 0x715018a6
No parameters
skim 0xbc25cf77
address _pendleMarket
returns: uint256
syncAllSupply 0xe5e933d3
No parameters
updateRewardTokens 0x9f08e497
address _pendleMarket
returns: bool
vote 0x698766ee
address[] _pools
uint64[] _weights
withdrawLock 0x5c388ca6
No parameters
returns: uint256
withdrawLp 0xa6c3ef8b
address _pendleMarket
address _to
uint256 _amount
Recent Transactions
No transactions found for this address