⾦库合约⾦库是⼀种智能合约,⽤户可以在其中存⼊代币(如USDT,DAI等)并获得股份作为回报。金库的亏损和盈利与他们存⼊的代币成正⽐例。⽤户可以提取他们的代币和收益。金库有两个重要接口function deposit(uint256 amount) external 用户存入代币function withdraw(uint256 _shares) external 用户归还份额获取代币收益⾦库推导充值和份额分配当⽤户将代币存⼊⾦库时,合约会根据⾦库代币总余额计算要发⾏的股份数,确保股份分配是公平;公式:s = a*T/BB 合约的总余额a 用户存入的代币数T 合约的总份额s 用户获取的份额提取资⾦归还⼀部分的share,换取对应的token。提款之后,流程逆转,share被销毁,⽤户收到他们的代币,⾦额会根据⾦库的收益或者损失进⾏调整公式:a = s*B/TB 合约的总余额a 返回用户的代币数T 合约的总份额s 用户获取的份额Inflation Attack通货膨胀冲击当你存⼊资产时,系统会计算你应该收到多少股份。然⽽,这个数字被取整到最接近的整数。这种取整有时会导致损失,特别是对于⼩额存款。案例:User 0 deposits 1User 0 transfer 100 * 1e18User 1 deposits 100 * 1e18User 0 withdraws all 200 * 1e18 + 1⽤户share⾦库balance⾦库shareUser 0 deposits 1111share=balanceUser 0 transfer 100 * 1e1811+100*1e181User 1 deposit 100 * 1e1801+200*1e181s=aT/B share=1001e181/(1+100*1e18) 1User 0 withdraws all000a=sB/T a=1(1+200*1e18)/1*攻击原理攻击者可以通过⾸先进⾏⼩额存款成为股东,然后向⾦库“捐赠”⼤量资产来利⽤这⼀点。这笔捐款⼤幅改变了汇率。当另⼀个⽤户进⾏存款时,扭曲的利率会导致他们的存款转换为更少的股份,甚⾄可能为零,从⽽有效地将他们的存款价值转移给攻击者。防范通货膨胀冲击1.通过在参数中设置最⼩允许的share,避免抢跑2.通过独⽴的变量记录⽤户充值余额3.让合约第⼀个充值,避免attacker恶意充值控制汇率4.通过OpenZeppelin 提供 ERC4626 精度偏移https://docs.openzeppelin.com/contracts/4.x/erc4626代码:Vault.sol//SPDX-License-Identifier: MITpragma solidity^0.8.21;import{IERC20}from"./IERC20.sol";contract Vault_test{IERC20publictoken;uint256publictotalshare;//总份额mapping(address=uint256)publicshare;//用户份额constructor(address _token){token=IERC20(_token);}//添加流水
金库合约Vault
⾦库合约⾦库是⼀种智能合约,⽤户可以在其中存⼊代币(如USDT,DAI等)并获得股份作为回报。金库的亏损和盈利与他们存⼊的代币成正⽐例。⽤户可以提取他们的代币和收益。金库有两个重要接口function deposit(uint256 amount) external 用户存入代币function withdraw(uint256 _shares) external 用户归还份额获取代币收益⾦库推导充值和份额分配当⽤户将代币存⼊⾦库时,合约会根据⾦库代币总余额计算要发⾏的股份数,确保股份分配是公平;公式:s = a*T/BB 合约的总余额a 用户存入的代币数T 合约的总份额s 用户获取的份额提取资⾦归还⼀部分的share,换取对应的token。提款之后,流程逆转,share被销毁,⽤户收到他们的代币,⾦额会根据⾦库的收益或者损失进⾏调整公式:a = s*B/TB 合约的总余额a 返回用户的代币数T 合约的总份额s 用户获取的份额Inflation Attack通货膨胀冲击当你存⼊资产时,系统会计算你应该收到多少股份。然⽽,这个数字被取整到最接近的整数。这种取整有时会导致损失,特别是对于⼩额存款。案例:User 0 deposits 1User 0 transfer 100 * 1e18User 1 deposits 100 * 1e18User 0 withdraws all 200 * 1e18 + 1⽤户share⾦库balance⾦库shareUser 0 deposits 1111share=balanceUser 0 transfer 100 * 1e1811+100*1e181User 1 deposit 100 * 1e1801+200*1e181s=aT/B share=1001e181/(1+100*1e18) 1User 0 withdraws all000a=sB/T a=1(1+200*1e18)/1*攻击原理攻击者可以通过⾸先进⾏⼩额存款成为股东,然后向⾦库“捐赠”⼤量资产来利⽤这⼀点。这笔捐款⼤幅改变了汇率。当另⼀个⽤户进⾏存款时,扭曲的利率会导致他们的存款转换为更少的股份,甚⾄可能为零,从⽽有效地将他们的存款价值转移给攻击者。防范通货膨胀冲击1.通过在参数中设置最⼩允许的share,避免抢跑2.通过独⽴的变量记录⽤户充值余额3.让合约第⼀个充值,避免attacker恶意充值控制汇率4.通过OpenZeppelin 提供 ERC4626 精度偏移https://docs.openzeppelin.com/contracts/4.x/erc4626代码:Vault.sol//SPDX-License-Identifier: MITpragma solidity^0.8.21;import{IERC20}from"./IERC20.sol";contract Vault_test{IERC20publictoken;uint256publictotalshare;//总份额mapping(address=uint256)publicshare;//用户份额constructor(address _token){token=IERC20(_token);}//添加流水