Skip to content

Commit

Permalink
audit: Add batch unstake method (#12)
Browse files Browse the repository at this point in the history
* feat: Add batch unstake method

* fix: Remove duplicate reentry check

* chore: Deploy new StakeManager on Mainnet

---------

Co-authored-by: akashiceth <[email protected]>
  • Loading branch information
thorseldon and akashiceth authored Mar 15, 2024
1 parent 7c5f72c commit 16ccc74
Show file tree
Hide file tree
Showing 5 changed files with 372 additions and 5 deletions.
354 changes: 354 additions & 0 deletions .openzeppelin/mainnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -2068,6 +2068,360 @@
}
}
}
},
"30c9555a72cb0a971e66cb72601010a4d5fdfaceedd951ae73dfcc0b74a6d0df": {
"address": "0xdbD4b3436Cb39Ca6A50a224cbc661d898Eaa73b6",
"txHash": "0x5d48791c0b5ff96e3d5c11099514b01e60aadb5d9aa8289288234d10d4004e03",
"layout": {
"solcVersion": "0.8.9",
"storage": [
{
"label": "_initialized",
"offset": 0,
"slot": "0",
"type": "t_uint8",
"contract": "Initializable",
"src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62",
"retypedFrom": "bool"
},
{
"label": "_initializing",
"offset": 1,
"slot": "0",
"type": "t_bool",
"contract": "Initializable",
"src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67"
},
{
"label": "__gap",
"offset": 0,
"slot": "1",
"type": "t_array(t_uint256)50_storage",
"contract": "ContextUpgradeable",
"src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36"
},
{
"label": "_owner",
"offset": 0,
"slot": "51",
"type": "t_address",
"contract": "OwnableUpgradeable",
"src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22"
},
{
"label": "__gap",
"offset": 0,
"slot": "52",
"type": "t_array(t_uint256)49_storage",
"contract": "OwnableUpgradeable",
"src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94"
},
{
"label": "_status",
"offset": 0,
"slot": "101",
"type": "t_uint256",
"contract": "ReentrancyGuardUpgradeable",
"src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:38"
},
{
"label": "__gap",
"offset": 0,
"slot": "102",
"type": "t_array(t_uint256)49_storage",
"contract": "ReentrancyGuardUpgradeable",
"src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:74"
},
{
"label": "_paused",
"offset": 0,
"slot": "151",
"type": "t_bool",
"contract": "PausableUpgradeable",
"src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:29"
},
{
"label": "__gap",
"offset": 0,
"slot": "152",
"type": "t_array(t_uint256)49_storage",
"contract": "PausableUpgradeable",
"src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:116"
},
{
"label": "__gap",
"offset": 0,
"slot": "201",
"type": "t_array(t_uint256)50_storage",
"contract": "ERC721HolderUpgradeable",
"src": "@openzeppelin/contracts-upgradeable/token/ERC721/utils/ERC721HolderUpgradeable.sol:40"
},
{
"label": "_stakedProxies",
"offset": 0,
"slot": "251",
"type": "t_struct(Proxies)16729_storage",
"contract": "StakeManager",
"src": "contracts/StakeManager.sol:45"
},
{
"label": "proxies",
"offset": 0,
"slot": "252",
"type": "t_mapping(t_contract(IStakeProxy)16287,t_bool)",
"contract": "StakeManager",
"src": "contracts/StakeManager.sol:46"
},
{
"label": "feeRecipient",
"offset": 0,
"slot": "253",
"type": "t_address",
"contract": "StakeManager",
"src": "contracts/StakeManager.sol:48"
},
{
"label": "fee",
"offset": 0,
"slot": "254",
"type": "t_uint256",
"contract": "StakeManager",
"src": "contracts/StakeManager.sol:49"
},
{
"label": "boundBayc",
"offset": 0,
"slot": "255",
"type": "t_contract(IBNFT)15598",
"contract": "StakeManager",
"src": "contracts/StakeManager.sol:51"
},
{
"label": "boundMayc",
"offset": 0,
"slot": "256",
"type": "t_contract(IBNFT)15598",
"contract": "StakeManager",
"src": "contracts/StakeManager.sol:52"
},
{
"label": "bayc",
"offset": 0,
"slot": "257",
"type": "t_contract(IERC721Upgradeable)2492",
"contract": "StakeManager",
"src": "contracts/StakeManager.sol:54"
},
{
"label": "mayc",
"offset": 0,
"slot": "258",
"type": "t_contract(IERC721Upgradeable)2492",
"contract": "StakeManager",
"src": "contracts/StakeManager.sol:55"
},
{
"label": "bakc",
"offset": 0,
"slot": "259",
"type": "t_contract(IERC721Upgradeable)2492",
"contract": "StakeManager",
"src": "contracts/StakeManager.sol:56"
},
{
"label": "apeCoin",
"offset": 0,
"slot": "260",
"type": "t_contract(IERC20Upgradeable)1419",
"contract": "StakeManager",
"src": "contracts/StakeManager.sol:58"
},
{
"label": "WETH",
"offset": 0,
"slot": "261",
"type": "t_contract(IWETH)16318",
"contract": "StakeManager",
"src": "contracts/StakeManager.sol:59"
},
{
"label": "apeStaking",
"offset": 0,
"slot": "262",
"type": "t_contract(IApeCoinStaking)15526",
"contract": "StakeManager",
"src": "contracts/StakeManager.sol:61"
},
{
"label": "proxyImplementation",
"offset": 0,
"slot": "263",
"type": "t_address",
"contract": "StakeManager",
"src": "contracts/StakeManager.sol:63"
},
{
"label": "matcher",
"offset": 0,
"slot": "264",
"type": "t_address",
"contract": "StakeManager",
"src": "contracts/StakeManager.sol:65"
},
{
"label": "lendPoolAddressedProvider",
"offset": 0,
"slot": "265",
"type": "t_contract(ILendPoolAddressesProvider)15821",
"contract": "StakeManager",
"src": "contracts/StakeManager.sol:67"
},
{
"label": "_approvedOperators",
"offset": 0,
"slot": "266",
"type": "t_mapping(t_address,t_address)",
"contract": "StakeManager",
"src": "contracts/StakeManager.sol:69"
},
{
"label": "_approvedLocker",
"offset": 0,
"slot": "267",
"type": "t_mapping(t_address,t_bool)",
"contract": "StakeManager",
"src": "contracts/StakeManager.sol:71"
}
],
"types": {
"t_address": {
"label": "address",
"numberOfBytes": "20"
},
"t_array(t_bytes32)dyn_storage": {
"label": "bytes32[]",
"numberOfBytes": "32"
},
"t_array(t_uint256)49_storage": {
"label": "uint256[49]",
"numberOfBytes": "1568"
},
"t_array(t_uint256)50_storage": {
"label": "uint256[50]",
"numberOfBytes": "1600"
},
"t_bool": {
"label": "bool",
"numberOfBytes": "1"
},
"t_bytes32": {
"label": "bytes32",
"numberOfBytes": "32"
},
"t_contract(IApeCoinStaking)15526": {
"label": "contract IApeCoinStaking",
"numberOfBytes": "20"
},
"t_contract(IBNFT)15598": {
"label": "contract IBNFT",
"numberOfBytes": "20"
},
"t_contract(IERC20Upgradeable)1419": {
"label": "contract IERC20Upgradeable",
"numberOfBytes": "20"
},
"t_contract(IERC721Upgradeable)2492": {
"label": "contract IERC721Upgradeable",
"numberOfBytes": "20"
},
"t_contract(ILendPoolAddressesProvider)15821": {
"label": "contract ILendPoolAddressesProvider",
"numberOfBytes": "20"
},
"t_contract(IStakeProxy)16287": {
"label": "contract IStakeProxy",
"numberOfBytes": "20"
},
"t_contract(IWETH)16318": {
"label": "contract IWETH",
"numberOfBytes": "20"
},
"t_mapping(t_address,t_address)": {
"label": "mapping(address => address)",
"numberOfBytes": "32"
},
"t_mapping(t_address,t_bool)": {
"label": "mapping(address => bool)",
"numberOfBytes": "32"
},
"t_mapping(t_address,t_mapping(t_uint256,t_struct(AddressSet)4349_storage))": {
"label": "mapping(address => mapping(uint256 => struct EnumerableSetUpgradeable.AddressSet))",
"numberOfBytes": "32"
},
"t_mapping(t_bytes32,t_uint256)": {
"label": "mapping(bytes32 => uint256)",
"numberOfBytes": "32"
},
"t_mapping(t_contract(IStakeProxy)16287,t_bool)": {
"label": "mapping(contract IStakeProxy => bool)",
"numberOfBytes": "32"
},
"t_mapping(t_uint256,t_struct(AddressSet)4349_storage)": {
"label": "mapping(uint256 => struct EnumerableSetUpgradeable.AddressSet)",
"numberOfBytes": "32"
},
"t_struct(AddressSet)4349_storage": {
"label": "struct EnumerableSetUpgradeable.AddressSet",
"members": [
{
"label": "_inner",
"type": "t_struct(Set)4048_storage",
"offset": 0,
"slot": "0"
}
],
"numberOfBytes": "64"
},
"t_struct(Proxies)16729_storage": {
"label": "struct NFTProxy.Proxies",
"members": [
{
"label": "_values",
"type": "t_mapping(t_address,t_mapping(t_uint256,t_struct(AddressSet)4349_storage))",
"offset": 0,
"slot": "0"
}
],
"numberOfBytes": "32"
},
"t_struct(Set)4048_storage": {
"label": "struct EnumerableSetUpgradeable.Set",
"members": [
{
"label": "_values",
"type": "t_array(t_bytes32)dyn_storage",
"offset": 0,
"slot": "0"
},
{
"label": "_indexes",
"type": "t_mapping(t_bytes32,t_uint256)",
"offset": 0,
"slot": "1"
}
],
"numberOfBytes": "64"
},
"t_uint256": {
"label": "uint256",
"numberOfBytes": "32"
},
"t_uint8": {
"label": "uint8",
"numberOfBytes": "1"
}
}
}
}
}
}
11 changes: 10 additions & 1 deletion contracts/StakeManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -276,11 +276,20 @@ contract StakeManager is
boundApe.setFlashLoanLocking(tokenId, msg.sender, locked);
}

function unStake(IStakeProxy proxy) external override onlyStakerOrOperator(proxy) nonReentrant {
function unStake(IStakeProxy proxy) public override onlyStakerOrOperator(proxy) nonReentrant {
require(!proxy.unStaked(), "StakeManager: already unStaked");
_flashUnStake(proxy);
}

/**
* @dev batch unStake, NO NEED to check nonReentrant and modifier cos reuse the unStake function
*/
function unStakeBatch(IStakeProxy[] calldata userProxies_) external {
for (uint256 i = 0; i < userProxies_.length; i++) {
unStake(userProxies_[i]);
}
}

function _flashUnStake(IStakeProxy proxy) internal {
DataTypes.ApeStaked memory apeStaked = proxy.apeStaked();
bytes memory param = abi.encode(proxy);
Expand Down
2 changes: 2 additions & 0 deletions contracts/interfaces/IStakeManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ interface IStakeManager {

function unStake(IStakeProxy proxy) external;

function unStakeBatch(IStakeProxy[] calldata userProxies_) external;

function claim(IStakeProxy proxy) external;

function claimFor(IStakeProxy proxy, address staker) external;
Expand Down
Loading

0 comments on commit 16ccc74

Please sign in to comment.