Skip to content

Commit

Permalink
feat: Ownable2Step coinbase (#1494)
Browse files Browse the repository at this point in the history
<!--- Please provide a general summary of your changes in the title
above -->

<!-- Give an estimate of the time you spent on this PR in terms of work
days.
Did you spend 0.5 days on this PR or rather 2 days?  -->

Time spent on this PR:

## Pull request type

<!-- Please try to limit your pull request to one type,
submit multiple pull requests if needed. -->

Please check the type of change your PR introduces:

- [ ] Bugfix
- [x] Feature
- [ ] Code style update (formatting, renaming)
- [ ] Refactoring (no functional changes, no api changes)
- [ ] Build related changes
- [ ] Documentation content changes
- [ ] Other (please describe):

## What is the current behavior?

<!-- Please describe the current behavior that you are modifying,
or link to a relevant issue. -->

Resolves #1488

## What is the new behavior?

<!-- Please describe the behavior or changes that are being added by
this PR. -->

Coinbase use Ownable2Step from OZ with version 5.0.2

<!-- Reviewable:start -->
- - -
This change is [<img src="https://reviewable.io/review_button.svg"
height="34" align="absmiddle"
alt="Reviewable"/>](https://reviewable.io/reviews/kkrt-labs/kakarot/1494)
<!-- Reviewable:end -->
  • Loading branch information
obatirou authored Oct 11, 2024
1 parent 9bbee4e commit b04587d
Show file tree
Hide file tree
Showing 7 changed files with 33 additions and 29 deletions.
5 changes: 4 additions & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
path = solidity_contracts/lib/v3-core
url = https://github.com/Uniswap/v3-core
[submodule "solidity_contracts/lib/openzeppelin"]
path = solidity_contracts/lib/openzeppelin
path = solidity_contracts/lib/openzeppelin-uniswapV3
url = https://github.com/OpenZeppelin/openzeppelin-contracts
[submodule "solidity_contracts/lib/base64-sol"]
path = solidity_contracts/lib/base64-sol
url = https://github.com/Brechtpd/base64
[submodule "solidity_contracts/lib/openzeppelin-contracts"]
path = solidity_contracts/lib/openzeppelin-contracts
url = https://github.com/OpenZeppelin/openzeppelin-contracts
2 changes: 2 additions & 0 deletions remappings.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@openzeppelin-contracts/=solidity_contracts/lib/openzeppelin-contracts/contracts/
openzeppelin/=solidity_contracts/lib/openzeppelin-uniswapV3/contracts/
1 change: 1 addition & 0 deletions solidity_contracts/lib/openzeppelin-contracts
Submodule openzeppelin-contracts added at dbb610
25 changes: 4 additions & 21 deletions solidity_contracts/src/Kakarot/Coinbase.sol
Original file line number Diff line number Diff line change
@@ -1,40 +1,23 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
pragma solidity 0.8.27;

import {DualVmToken} from "../CairoPrecompiles/DualVmToken.sol";
import {Ownable2Step, Ownable} from "@openzeppelin-contracts/access/Ownable2Step.sol";

contract Coinbase {
contract Coinbase is Ownable2Step {
/// @dev The EVM address of the DualVmToken for Kakarot ETH.
DualVmToken public immutable kakarotEth;

/// @dev State variable to store the owner of the contract
address public owner;

/// Constructor sets the owner of the contract
constructor(address _kakarotEth) {
owner = msg.sender;
constructor(address _kakarotEth) Ownable(msg.sender) {
kakarotEth = DualVmToken(_kakarotEth);
}

/// Modifier to restrict access to owner only
/// @dev Assert that msd.sender is the owner
modifier onlyOwner() {
require(msg.sender == owner, "Not the contract owner");
_;
}

/// @notice Withdraws ETH from the contract to a Starknet address
/// @dev DualVmToken.balanceOf(this) is the same as address(this).balance
/// @param toStarknetAddress The Starknet address to withdraw to
function withdraw(uint256 toStarknetAddress) external onlyOwner {
uint256 balance = address(this).balance;
kakarotEth.transfer(toStarknetAddress, balance);
}

/// @notice Transfers ownership of the contract to a new address
/// @param newOwner The address to transfer ownership to
function transferOwnership(address newOwner) external onlyOwner {
require(newOwner != address(0), "New owner cannot be the zero address");
owner = newOwner;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ library UniswapV2Library {
hex"ff",
factory,
keccak256(abi.encodePacked(token0, token1)),
hex"f1cfdd2c3c5d1c1326d5ea2b5624ae1ad7c2445c6b96eabc5af1dd53cdf64243" // init code hash
hex"de99574e4d2f5d518d4322aaa25cf5c57d167d84b40c189e60afca95b87d6cdd" // init code hash
)
)
)
Expand Down
27 changes: 21 additions & 6 deletions tests/end_to_end/Kakarot/test_coinbase.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import pytest
import pytest_asyncio
from eth_abi import encode
from eth_utils import keccak
from eth_utils.address import to_checksum_address

from kakarot_scripts.utils.kakarot import deploy, eth_balance_of, fund_address
from kakarot_scripts.utils.starknet import invoke
Expand Down Expand Up @@ -39,23 +42,35 @@ async def test_should_withdraw_all_eth(self, coinbase, owner):
assert balance_owner - balance_owner_prev + tx["gas_used"] == 0.001e18

async def test_should_revert_when_not_owner(self, coinbase, other):
with evm_error("Not the contract owner"):
error = keccak(b"OwnableUnauthorizedAccount(address)")[:4] + encode(
["address"], [other.address]
)
with evm_error(error):
await coinbase.withdraw(0xDEAD, caller_eoa=other.starknet_contract)

class TestTransferOwnership:

async def test_should_transfer_ownership(self, coinbase, owner, other):
# initiate transfer process
await coinbase.transferOwnership(other.address)
assert await coinbase.pendingOwner() == other.address
assert await coinbase.owner() == owner.address
# accept the transfer
await coinbase.acceptOwnership(caller_eoa=other.starknet_contract)
ZERO_ADDRESS = to_checksum_address(f"0x{0:040x}")
assert await coinbase.pendingOwner() == ZERO_ADDRESS
assert await coinbase.owner() == other.address
# teardown
await coinbase.transferOwnership(
owner.address, caller_eoa=other.starknet_contract
)

async def test_should_revert_when_new_owner_is_zero_address(self, coinbase):
with evm_error("New owner cannot be the zero address"):
await coinbase.transferOwnership(f"0x{0:040x}")
await coinbase.acceptOwnership(caller_eoa=owner.starknet_contract)

async def test_should_revert_when_not_owner(self, coinbase, other):
with evm_error("Not the contract owner"):
error = keccak(b"OwnableUnauthorizedAccount(address)")[:4] + encode(
["address"], [other.address]
)
with evm_error(error):
await coinbase.transferOwnership(
other.address, caller_eoa=other.starknet_contract
)

0 comments on commit b04587d

Please sign in to comment.