-
-
Save 08xmt/b874309caad6abb81216e123f89d80dd to your computer and use it in GitHub Desktop.
Quick and dirty simulation of transaction payload found in https://forum.balancer.fi/t/bip-299-permissioned-arbitrage-to-recover-remaining-funds-in-bb-e-usd/4783
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: UNLICENSED | |
pragma solidity ^0.8.13; | |
import "forge-std/Test.sol"; | |
interface IAuthorizer { | |
function grantRoles(bytes32[] calldata roles, address account) external; | |
function revokeRoles(bytes32[] calldata roles, address account) external; | |
} | |
interface ILT { | |
function unpause() external; | |
} | |
interface IAsset{ | |
} | |
interface IVault { | |
enum UserBalanceOpKind { DEPOSIT_INTERNAL, WITHDRAW_INTERNAL, TRANSFER_INTERNAL, TRANSFER_EXTERNAL } | |
struct UserBalanceOp { | |
UserBalanceOpKind kind; | |
IAsset asset; | |
uint256 amount; | |
address sender; | |
address payable recipient; | |
} | |
function manageUserBalance(UserBalanceOp[] memory ops) external payable; | |
} | |
interface IRescueContract { | |
function do_arb(address[] calldata inputTokens, address[] calldata outputTokens, uint[] calldata dustFactors, address recipient) external; | |
} | |
interface IERC20 { | |
function balanceOf(address holder) external view returns (uint); | |
} | |
contract RescueSimTest is Test { | |
address balancerMsig = 0x10A19e7eE7d7F8a52822f6817de8ea18204F2e4f; | |
address usdc = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; | |
address dai = 0x6B175474E89094C44Da98b954EedeAC495271d0F; | |
IAuthorizer authorizer = IAuthorizer(0xA331D84eC860Bf466b4CdCcFb4aC09a1B43F3aE6); | |
ILT usdcLinearPool = ILT(0xD4e7C1F3DA1144c9E2CfD1b015eDA7652b4a4399); | |
ILT daiLinearPool = ILT(0xeB486AF868AeB3b6e53066abc9623b1041b42bc0); | |
IVault vault = IVault(0xBA12222222228d8Ba445958a75a0704d566BF2C8); | |
IRescueContract rescueContract = IRescueContract(0xF23d8342881eDECcED51EA694AC21C2B68440929); | |
IVault.UserBalanceOp[] ops; | |
bytes32[] roles; | |
address[] inputTokens; | |
address[] outputTokens; | |
uint[] dustFactors; | |
function setUp() public { | |
inputTokens.push(address(usdcLinearPool)); | |
inputTokens.push(address(daiLinearPool)); | |
outputTokens.push(usdc); | |
outputTokens.push(dai); | |
dustFactors.push(350); | |
dustFactors.push(300); | |
roles.push(bytes32(0xba620d90bf43ed4e28d08953a56a063710cfccbbc468b90ec556433bb1b0b27f)); | |
} | |
function testRescue() public { | |
uint usdcBalanceBefore = IERC20(usdc).balanceOf(balancerMsig); | |
uint daiBalanceBefore = IERC20(dai).balanceOf(balancerMsig); | |
vm.startPrank(balancerMsig); | |
authorizer.grantRoles(roles, balancerMsig); | |
usdcLinearPool.unpause(); | |
daiLinearPool.unpause(); | |
ops.push(IVault.UserBalanceOp( | |
IVault.UserBalanceOpKind(2), | |
IAsset(0xEb91861f8A4e1C12333F42DCE8fB0Ecdc28dA716), | |
2804709054674049019658430, | |
balancerMsig, | |
payable(address(rescueContract)) | |
) | |
); | |
vault.manageUserBalance(ops); | |
ops[0] = IVault.UserBalanceOp( | |
IVault.UserBalanceOpKind(2), | |
IAsset(0xe025E3ca2bE02316033184551D4d3Aa22024D9DC), | |
2332180919384747028677979, | |
balancerMsig, | |
payable(address(rescueContract)) | |
); | |
vault.manageUserBalance(ops); | |
rescueContract.do_arb( | |
inputTokens, | |
outputTokens, | |
dustFactors, | |
balancerMsig | |
); | |
authorizer.revokeRoles(roles, balancerMsig); | |
vm.stopPrank(); | |
emit log_named_uint("Additional USDC Balance In Balancer Msig", IERC20(usdc).balanceOf(balancerMsig) - usdcBalanceBefore); | |
emit log_named_uint("Additional DAI Balance In Balancer Msig", IERC20(dai).balanceOf(balancerMsig) - daiBalanceBefore); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment