Skip to content

Commit

Permalink
v0.7
Browse files Browse the repository at this point in the history
  • Loading branch information
remollemo committed Jan 31, 2024
1 parent a4caa78 commit d62a255
Show file tree
Hide file tree
Showing 26 changed files with 3,139 additions and 563 deletions.
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
black==23.1a1
cairo-lang==0.11.2
web3==5.31.3
pytest==7.4.4
3 changes: 2 additions & 1 deletion scripts/build-cairo.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ pushd $(dirname $0)/..
set -e
mkdir -p cairo_contracts

scripts/starknet-compile.py src --contract-path src::strk::erc20_lockable::ERC20Lockable cairo_contracts/ERC20Lockable.sierra
scripts/starknet-compile.py src --contract-path src::update_712_vars_eic::Update712VarsEIC cairo_contracts/Update712VarsEIC.sierra
scripts/starknet-compile.py src --contract-path src::roles_init_eic::RolesExternalInitializer cairo_contracts/RolesExternalInitializer.sierra
scripts/starknet-compile.py src --contract-path src::legacy_bridge_eic::LegacyBridgeUpgradeEIC cairo_contracts/LegacyBridgeUpgradeEIC.sierra
scripts/starknet-compile.py src --contract-path src::token_bridge::TokenBridge cairo_contracts/TokenBridge.sierra
scripts/starknet-compile.py src --contract-path openzeppelin::token::erc20::presets::erc20votes::ERC20VotesPreset cairo_contracts/ERC20VotesPreset.sierra
scripts/starknet-compile.py src --contract-path openzeppelin::token::erc20::presets::erc20_votes_lock::ERC20VotesLock cairo_contracts/ERC20VotesLock.sierra
scripts/starknet-compile.py src --contract-path openzeppelin::token::erc20_v070::erc20::ERC20 cairo_contracts/ERC20.sierra
set +e
popd
6 changes: 6 additions & 0 deletions src/cairo/err_msg.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,17 @@ mod ERC20Errors {

mod AccessErrors {
const INVALID_MINTER: felt252 = 'INVALID_MINTER_ADDRESS';
const INVALID_TOKEN: felt252 = 'INVALID_TOKEN_ADDRESS';
const CALLER_MISSING_ROLE: felt252 = 'CALLER_IS_MISSING_ROLE';
const ZERO_ADDRESS: felt252 = 'INVALID_ACCOUNT_ADDRESS';
const ALREADY_INITIALIZED: felt252 = 'ROLES_ALREADY_INITIALIZED';
const ZERO_ADDRESS_GOV_ADMIN: felt252 = 'ZERO_PROVISIONAL_GOV_ADMIN';
const ONLY_APP_GOVERNOR: felt252 = 'ONLY_APP_GOVERNOR';
const ONLY_OPERATOR: felt252 = 'ONLY_OPERATOR';
const ONLY_TOKEN_ADMIN: felt252 = 'ONLY_TOKEN_ADMIN';
const ONLY_UPGRADE_GOVERNOR: felt252 = 'ONLY_UPGRADE_GOVERNOR';
const ONLY_SECURITY_ADMIN: felt252 = 'ONLY_SECURITY_ADMIN';
const ONLY_SECURITY_AGENT: felt252 = 'ONLY_SECURITY_AGENT';
const ONLY_MINTER: felt252 = 'MINTER_ONLY';
const ONLY_SELF_CAN_RENOUNCE: felt252 = 'ONLY_SELF_CAN_RENOUNCE';
const GOV_ADMIN_CANNOT_RENOUNCE: felt252 = 'GOV_ADMIN_CANNOT_SELF_REMOVE';
Expand Down
5 changes: 0 additions & 5 deletions src/cairo/legacy_bridge_tester.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -145,34 +145,29 @@ mod LegacyBridgeTester {
impl internals of _internals {
fn only_upgrade_governor(self: @ContractState) {}

// Returns if finalized.
fn is_finalized(self: @ContractState) -> bool {
self.finalized.read()
}

// Sets the implementation as finalized.
fn finalize(ref self: ContractState) {
self.finalized.write(true);
}


// Sets the implementation activation time.
fn set_impl_activation_time(
ref self: ContractState, implementation_data: ImplementationData, activation_time: u64
) {
let impl_key = calc_impl_key(:implementation_data);
self.impl_activation_time.write(impl_key, activation_time);
}

// Returns the implementation activation time.
fn get_impl_expiration_time(
self: @ContractState, implementation_data: ImplementationData
) -> u64 {
let impl_key = calc_impl_key(:implementation_data);
self.impl_expiration_time.read(impl_key)
}

// Sets the implementation expiration time.
fn set_impl_expiration_time(
ref self: ContractState, implementation_data: ImplementationData, expiration_time: u64
) {
Expand Down
16 changes: 8 additions & 8 deletions src/cairo/legacy_eic_test.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ mod legacy_eic_test {
use serde::Serde;
use starknet::class_hash::{ClassHash, class_hash_const};
use starknet::{ContractAddress, EthAddress, EthAddressZeroable, syscalls::deploy_syscall};
use openzeppelin::token::erc20::presets::erc20votes::ERC20VotesPreset::{
use openzeppelin::token::erc20::presets::erc20_votes_lock::ERC20VotesLock::{
DAPP_NAME, DAPP_VERSION
};

Expand All @@ -24,7 +24,7 @@ mod legacy_eic_test {
use src::roles_interface::{IRolesDispatcher, IRolesDispatcherTrait};
use src::test_utils::test_utils::{
caller, get_roles, get_token_bridge, set_contract_address_as_caller, get_replaceable,
simple_deploy_l2_token, DEFAULT_UPGRADE_DELAY
simple_deploy_token, DEFAULT_UPGRADE_DELAY
};
use src::token_bridge_interface::{ITokenBridgeDispatcher, ITokenBridgeDispatcherTrait};
use src::token_bridge::TokenBridge;
Expand Down Expand Up @@ -181,8 +181,8 @@ mod legacy_eic_test {
#[test]
#[available_gas(30000000)]
fn test_happy_path() {
let l2_token = simple_deploy_l2_token();
let tester_address = deploy_legacy_tester(l2_token);
let l2_token = simple_deploy_token();
let tester_address = deploy_legacy_tester(:l2_token);
let impl_data = token_bridge_w_eic_implementation_data(
l1_token: L1_TOKEN_ADDRESS(), :l2_token,
);
Expand All @@ -191,7 +191,7 @@ mod legacy_eic_test {
);

let token_bridge = get_token_bridge(tester_address);
let l1_token = token_bridge.get_l1_token(l2_token);
let l1_token = token_bridge.get_l1_token(:l2_token);
let l2_token_actual = token_bridge.get_l2_token(L1_TOKEN_ADDRESS());
assert(L1_TOKEN_ADDRESS() == l1_token, 'L1_ZEROED');
assert(l2_token == l2_token_actual, 'L2_ZEROED');
Expand All @@ -206,7 +206,7 @@ mod legacy_eic_test {
add_impl_and_replace_to(replaceable_address: tester1, :implementation_data);

// Tester 1 roles are not initialzied, and gov admin not set.
let roles1 = get_roles(tester1);
let roles1 = get_roles(contract_address: tester1);
assert(!roles1.is_governance_admin(caller()), 'Roles should not be initialized');
assert(!roles1.is_upgrade_governor(caller()), 'Roles should not be initialized');
assert(!roles1.is_security_admin(caller()), 'Roles should not be initialized');
Expand All @@ -217,7 +217,7 @@ mod legacy_eic_test {
add_impl_and_replace_to(replaceable_address: tester2, :implementation_data);

// Tester 2 roles are initialized and gov admin assigned.
let roles = get_roles(tester2);
let roles = get_roles(contract_address: tester2);
assert(roles.is_governance_admin(caller()), 'Roles should be initialized');
assert(roles.is_upgrade_governor(caller()), 'Roles should be initialized');
assert(roles.is_security_admin(caller()), 'Roles should be initialized');
Expand Down Expand Up @@ -322,7 +322,7 @@ mod legacy_eic_test {
#[available_gas(30000000)]
fn test_upgrade_an_upgraded() {
// Test failing to upgrade twice.
let l2_token = simple_deploy_l2_token();
let l2_token = simple_deploy_token();
let tester_address = deploy_legacy_tester(l2_token);
let impl_data = token_bridge_w_eic_implementation_data(
l1_token: L1_TOKEN_ADDRESS(), :l2_token,
Expand Down
4 changes: 4 additions & 0 deletions src/cairo/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
// STRK Token (ERC20Lockable).
mod strk;

// Interfaces.
mod access_control_interface;
mod token_bridge_admin_interface;
mod token_bridge_interface;
mod erc20_interface;
mod mintable_token_interface;
mod mintable_lock_interface;
mod replaceability_interface;
mod roles_interface;
mod receiver_interface;
Expand Down
48 changes: 48 additions & 0 deletions src/cairo/mintable_lock_interface.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use starknet::ContractAddress;

#[starknet::interface]
trait IMintableLock<TContractState> {
fn permissioned_lock_and_delegate(
ref self: TContractState, account: ContractAddress, delegatee: ContractAddress, amount: u256
);
}

#[starknet::interface]
trait ILockingContract<TContractState> {
fn set_locking_contract(ref self: TContractState, locking_contract: ContractAddress);
fn get_locking_contract(self: @TContractState) -> ContractAddress;
}

#[starknet::interface]
trait ILockAndDelegate<TContractState> {
fn lock_and_delegate(ref self: TContractState, delegatee: ContractAddress, amount: u256);
fn lock_and_delegate_by_sig(
ref self: TContractState,
account: ContractAddress,
delegatee: ContractAddress,
amount: u256,
nonce: felt252,
expiry: u64,
signature: Array<felt252>
);
}

#[starknet::interface]
trait ITokenLock<TContractState> {
fn lock(ref self: TContractState, amount: u256);
fn unlock(ref self: TContractState, amount: u256);
}

#[derive(Copy, Drop, PartialEq, starknet::Event)]
struct Locked {
#[key]
account: ContractAddress,
amount: u256
}

#[derive(Copy, Drop, PartialEq, starknet::Event)]
struct Unlocked {
#[key]
account: ContractAddress,
amount: u256
}
91 changes: 6 additions & 85 deletions src/cairo/permissioned_token_test.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ mod permissioned_token_test {
use integer::BoundedInt;
use serde::Serde;
use starknet::{contract_address_const, ContractAddress, syscalls::deploy_syscall};
use src::err_msg::AccessErrors as AccessErrors;

use super::super::mintable_token_interface::{
IMintableTokenDispatcher, IMintableTokenDispatcherTrait
};
use super::super::erc20_interface::{IERC20Dispatcher, IERC20DispatcherTrait};
use super::super::test_utils::test_utils::{
get_erc20_token, deploy_l2_votes_token, deploy_l2_token, get_mintable_token,
get_l2_token_deployment_calldata
get_erc20_token, deploy_l2_token, get_mintable_token, get_l2_token_deployment_calldata
};

use openzeppelin::token::erc20::presets::erc20votes::ERC20VotesPreset;
use openzeppelin::token::erc20::presets::erc20_votes_lock::ERC20VotesLock;
use openzeppelin::token::erc20_v070::erc20::ERC20;

fn _l2_erc20(initial_supply: u256) -> ContractAddress {
Expand All @@ -28,23 +28,6 @@ mod permissioned_token_test {
deploy_l2_token(:initial_owner, :permitted_minter, :initial_supply)
}

fn _l2_votes_erc20(initial_supply: u256) -> ContractAddress {
let initial_owner = starknet::contract_address_const::<10>();
let permitted_minter = starknet::contract_address_const::<20>();
deploy_l2_votes_token(:initial_owner, :permitted_minter, :initial_supply)
}

#[test]
#[available_gas(30000000)]
fn test_votes_erc20_successful_permitted_mint() {
let initial_owner = starknet::contract_address_const::<10>();
let permitted_minter = starknet::contract_address_const::<20>();
let l2_token = deploy_l2_votes_token(
:initial_owner, :permitted_minter, initial_supply: 1000
);
_successful_permitted_mint(:l2_token, :initial_owner, :permitted_minter);
}

#[test]
#[available_gas(30000000)]
fn test_erc20_successful_permitted_mint() {
Expand Down Expand Up @@ -85,21 +68,6 @@ mod permissioned_token_test {
);
}

#[test]
#[should_panic(expected: ('u256_add Overflow', 'ENTRYPOINT_FAILED',))]
#[available_gas(30000000)]
fn test_votes_erc20_overflowing_permitted_mint() {
// Setup.
let initial_owner = starknet::contract_address_const::<10>();
let permitted_minter = starknet::contract_address_const::<20>();

// Deploy the l2 token contract.
let l2_token = deploy_l2_votes_token(
:initial_owner, :permitted_minter, initial_supply: BoundedInt::max()
);
_overflowing_permitted_mint(:l2_token, :initial_owner, :permitted_minter);
}

#[test]
#[should_panic(expected: ('u256_add Overflow', 'ENTRYPOINT_FAILED',))]
#[available_gas(30000000)]
Expand All @@ -125,14 +93,6 @@ mod permissioned_token_test {
mintable_token.permissioned_mint(account: mint_recipient, amount: 1);
}

#[test]
#[should_panic(expected: ('MINTER_ONLY', 'ENTRYPOINT_FAILED',))]
#[available_gas(30000000)]
fn test_votes_erc20_unpermitted_permitted_mint() {
let l2_token = _l2_votes_erc20(initial_supply: 1000);
_unpermitted_permitted_mint(:l2_token);
}

#[test]
#[should_panic(expected: ('MINTER_ONLY', 'ENTRYPOINT_FAILED',))]
#[available_gas(30000000)]
Expand Down Expand Up @@ -170,19 +130,10 @@ mod permissioned_token_test {
.unwrap_err()
.span();
assert(error_message.len() == 2, 'UNEXPECTED_ERROR_LEN_MISMATCH');
assert(error_message.at(0) == @'INVALID_MINTER_ADDRESS', 'INVALID_MINTER_ADDRESS_ERROR');
assert(error_message.at(1) == @'CONSTRUCTOR_FAILED', 'CONSTRUCTOR_ERROR_MISMATCH');
}

#[test]
#[available_gas(30000000)]
fn test_votes_erc20_successful_permitted_burn() {
let initial_owner = starknet::contract_address_const::<10>();
let permitted_minter = starknet::contract_address_const::<20>();
let l2_token = deploy_l2_votes_token(
:initial_owner, :permitted_minter, initial_supply: 1000
assert(
error_message.at(0) == @AccessErrors::INVALID_MINTER, 'INVALID_MINTER_ADDRESS_ERROR'
);
_successful_permitted_burn(:l2_token, :initial_owner, :permitted_minter);
assert(error_message.at(1) == @'CONSTRUCTOR_FAILED', 'CONSTRUCTOR_ERROR_MISMATCH');
}

#[test]
Expand Down Expand Up @@ -216,21 +167,6 @@ mod permissioned_token_test {
assert(erc20_token.total_supply() == expected_after, 'TOTAL_SUPPLY_PERM_BURN_ERROR');
}

#[test]
#[should_panic(expected: ('u256_sub Overflow', 'ENTRYPOINT_FAILED',))]
#[available_gas(30000000)]
fn test_votes_erc20_exceeding_amount_permitted_burn() {
// Setup.
let initial_owner = starknet::contract_address_const::<10>();
let permitted_minter = starknet::contract_address_const::<20>();

// Deploy the l2 token contract.
let l2_token = deploy_l2_votes_token(
:initial_owner, :permitted_minter, initial_supply: 1000
);
_exceeding_amount_permitted_burn(:l2_token, :initial_owner, :permitted_minter);
}

#[test]
#[should_panic(expected: ('u256_sub Overflow', 'ENTRYPOINT_FAILED',))]
#[available_gas(30000000)]
Expand All @@ -254,21 +190,6 @@ mod permissioned_token_test {
mintable_token.permissioned_burn(account: initial_owner, amount: 1001);
}

#[test]
#[should_panic(expected: ('MINTER_ONLY', 'ENTRYPOINT_FAILED',))]
#[available_gas(30000000)]
fn test_votes_erc20_unpermitted_permitted_burn() {
// Setup.
let initial_owner = starknet::contract_address_const::<10>();
let permitted_minter = starknet::contract_address_const::<20>();

// Deploy the l2 token contract.
let l2_token = deploy_l2_votes_token(
:initial_owner, :permitted_minter, initial_supply: 1000
);
_unpermitted_permitted_burn(:l2_token, :initial_owner, :permitted_minter);
}

#[test]
#[should_panic(expected: ('MINTER_ONLY', 'ENTRYPOINT_FAILED',))]
#[available_gas(30000000)]
Expand Down
Loading

0 comments on commit d62a255

Please sign in to comment.