
OlympusDAO $300,000 exploit
Two days ago on October 21st 2022, OlympusDAO was drained of 30,437 OHM Tokens (about $300,000) due to an exploit in Bond Protocol. This exploit was surprisingly simple, but nonetheless was not caught during audit. I’ll be going over how the exploit was carried out along with a proof of concept here.BackgroundFirst a quick tl;dr of what bonding is. OlympusDAO uses this approach to generate capital. Essentially, users lock up their LP tokens in exchange for OHM tokens at a discounted rate. By ...
Ethernaut 15: Preservation
The ethernaut rabbit hole continues. This is my solution for the 15th challenge: Preservation https://ethernaut.openzeppelin.com/level/0x97E982a15FbB1C28F6B8ee971BEc15C78b3d263FInvestigationWe have a contract that has some time zone library addresses defined. Each of these libraries can be used to set the storedTime value on the Preservation instance. The library code being used has also been highlighted at the bottomcontract Preservation { // public library contracts address public timeZone1...
Ethernaut 5: Token
My solution for the fifth ethernaut challenge: https://ethernaut.openzeppelin.com/level/0x63bE8347A617476CA461649897238A31835a32CEInvestigationWe have a Token contract that contains balances for address and a total supply.mapping(address => uint) balances; uint public totalSupply; We have a constructor which initializes a contract instance with a provided supply and gives that entire balance to the contract deployerconstructor(uint _initialSupply) public { balances[msg.sender] = totalSupply =...
Writing about security, MEV, privacy and decentralized finance
This is my solution for the 14th ethernaut challenge, Naught Coin
https://ethernaut.openzeppelin.com/level/0x97E982a15FbB1C28F6B8ee971BEc15C78b3d263F
We have a smart contract which inherits the ERC20 implementation from OpenZeppelin
import '@openzeppelin/contracts/token/ERC20/ERC20.sol';
contract NaughtCoin is ERC20 {
// string public constant name = 'NaughtCoin';
// string public constant symbol = '0x0';
// uint public constant decimals = 18;
uint public timeLock = now + 10 * 365 days;
uint256 public INITIAL_SUPPLY;
address public player;
constructor(address _player)
ERC20('NaughtCoin', '0x0')
public {
player = _player;
INITIAL_SUPPLY = 1000000 * (10**uint256(decimals()));
// _totalSupply = INITIAL_SUPPLY;
// _balances[player] = INITIAL_SUPPLY;
_mint(player, INITIAL_SUPPLY);
emit Transfer(address(0), player, INITIAL_SUPPLY);
}
function transfer(address _to, uint256 _value) override public lockTokens returns(bool) {
super.transfer(_to, _value);
}
// Prevent the initial owner from transferring tokens until the timelock has passed
modifier lockTokens() {
if (msg.sender == player) {
require(now > timeLock);
_;
} else {
_;
}
}
}
It adds on some implementation detail which prevents the owner from transferring tokens out until it has been a year since the contract was created. The challenge here is to transfer the tokens out to some other address
I found that this was one of the easier ethernaut challenges. Looking through the ERC20 implementation by OpenZeppelin, I found that there are additional ways to transfer tokens other than the transfer method which has been overriden above. Specifically, I was interested in the transferFrom method. The function signature looks like this
transferFrom(address sender, address recipient, uint256 amount) → bool
This function uses the “allowance” mechanism from ERC20. All this means is that accounts can allow other accounts to spend tokens on their behalf. In my case, I decided I can just allow my own account to spend tokens, and then use transferFrom to send those tokens to another address.
await contract.increaseAllowance(player, "1000000000000000000000000")
await contract.transferFrom(player, "<other address>", "1000000000000000000000000")
And voila, the level is cracked.
Overriding functions works to add custom authorization behaviour, but we have to be careful about all the mechanisms that we need to override
I also learned about the full implementation of ERC20 from OpenZeppelin
This is my solution for the 14th ethernaut challenge, Naught Coin
https://ethernaut.openzeppelin.com/level/0x97E982a15FbB1C28F6B8ee971BEc15C78b3d263F
We have a smart contract which inherits the ERC20 implementation from OpenZeppelin
import '@openzeppelin/contracts/token/ERC20/ERC20.sol';
contract NaughtCoin is ERC20 {
// string public constant name = 'NaughtCoin';
// string public constant symbol = '0x0';
// uint public constant decimals = 18;
uint public timeLock = now + 10 * 365 days;
uint256 public INITIAL_SUPPLY;
address public player;
constructor(address _player)
ERC20('NaughtCoin', '0x0')
public {
player = _player;
INITIAL_SUPPLY = 1000000 * (10**uint256(decimals()));
// _totalSupply = INITIAL_SUPPLY;
// _balances[player] = INITIAL_SUPPLY;
_mint(player, INITIAL_SUPPLY);
emit Transfer(address(0), player, INITIAL_SUPPLY);
}
function transfer(address _to, uint256 _value) override public lockTokens returns(bool) {
super.transfer(_to, _value);
}
// Prevent the initial owner from transferring tokens until the timelock has passed
modifier lockTokens() {
if (msg.sender == player) {
require(now > timeLock);
_;
} else {
_;
}
}
}
It adds on some implementation detail which prevents the owner from transferring tokens out until it has been a year since the contract was created. The challenge here is to transfer the tokens out to some other address
I found that this was one of the easier ethernaut challenges. Looking through the ERC20 implementation by OpenZeppelin, I found that there are additional ways to transfer tokens other than the transfer method which has been overriden above. Specifically, I was interested in the transferFrom method. The function signature looks like this
transferFrom(address sender, address recipient, uint256 amount) → bool
This function uses the “allowance” mechanism from ERC20. All this means is that accounts can allow other accounts to spend tokens on their behalf. In my case, I decided I can just allow my own account to spend tokens, and then use transferFrom to send those tokens to another address.
await contract.increaseAllowance(player, "1000000000000000000000000")
await contract.transferFrom(player, "<other address>", "1000000000000000000000000")
And voila, the level is cracked.
Overriding functions works to add custom authorization behaviour, but we have to be careful about all the mechanisms that we need to override
I also learned about the full implementation of ERC20 from OpenZeppelin

OlympusDAO $300,000 exploit
Two days ago on October 21st 2022, OlympusDAO was drained of 30,437 OHM Tokens (about $300,000) due to an exploit in Bond Protocol. This exploit was surprisingly simple, but nonetheless was not caught during audit. I’ll be going over how the exploit was carried out along with a proof of concept here.BackgroundFirst a quick tl;dr of what bonding is. OlympusDAO uses this approach to generate capital. Essentially, users lock up their LP tokens in exchange for OHM tokens at a discounted rate. By ...
Ethernaut 15: Preservation
The ethernaut rabbit hole continues. This is my solution for the 15th challenge: Preservation https://ethernaut.openzeppelin.com/level/0x97E982a15FbB1C28F6B8ee971BEc15C78b3d263FInvestigationWe have a contract that has some time zone library addresses defined. Each of these libraries can be used to set the storedTime value on the Preservation instance. The library code being used has also been highlighted at the bottomcontract Preservation { // public library contracts address public timeZone1...
Ethernaut 5: Token
My solution for the fifth ethernaut challenge: https://ethernaut.openzeppelin.com/level/0x63bE8347A617476CA461649897238A31835a32CEInvestigationWe have a Token contract that contains balances for address and a total supply.mapping(address => uint) balances; uint public totalSupply; We have a constructor which initializes a contract instance with a provided supply and gives that entire balance to the contract deployerconstructor(uint _initialSupply) public { balances[msg.sender] = totalSupply =...
Share Dialog
Share Dialog
Writing about security, MEV, privacy and decentralized finance

Subscribe to 0xbanky

Subscribe to 0xbanky
<100 subscribers
<100 subscribers
No activity yet