Skip to content

Commit

Permalink
update contracts and tests for cairo 2.5.x
Browse files Browse the repository at this point in the history
  • Loading branch information
augustbleeds committed Feb 23, 2024
1 parent 6c48b26 commit 08fdb4a
Show file tree
Hide file tree
Showing 28 changed files with 517 additions and 431 deletions.
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ mockery 2.22.1
golangci-lint 1.55.0
actionlint 1.6.12
shellcheck 0.8.0
scarb 0.7.0
scarb 2.5.4

# Kubernetes
k3d 5.4.4
Expand Down
4 changes: 2 additions & 2 deletions contracts/Scarb.lock
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ dependencies = [

[[package]]
name = "openzeppelin"
version = "0.8.0"
source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.8.0#c23e8e96de60e6e3159b1ff8591a1187269c0eb7"
version = "0.9.0"
source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.9.0#861fc416f87addbe23a3b47f9d19ab27c10d5dc8"
2 changes: 1 addition & 1 deletion contracts/Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ sierra = "cairo-compile . -r"
# Note: currently testing doesn't work with dependencies
[dependencies]
starknet = ">=1.3.0"
openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.8.0" }
openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.9.0" }

[lib]

Expand Down
10 changes: 6 additions & 4 deletions contracts/src/access_control/access_controller.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@ mod AccessController {
use starknet::ContractAddress;
use starknet::class_hash::ClassHash;

use openzeppelin::access::ownable::ownable::OwnableComponent;

use chainlink::libraries::access_control::{AccessControlComponent, IAccessController};
use chainlink::libraries::ownable::{OwnableComponent, IOwnable};
// use chainlink::libraries::ownable::{OwnableComponent, IOwnable};
use chainlink::libraries::type_and_version::ITypeAndVersion;
use chainlink::libraries::upgradeable::{Upgradeable, IUpgradeable};

component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
component!(path: AccessControlComponent, storage: access_control, event: AccessControlEvent);

#[abi(embed_v0)]
impl OwnableImpl = OwnableComponent::OwnableImpl<ContractState>;
impl InternalImpl = OwnableComponent::InternalImpl<ContractState>;
impl OwnableImpl = OwnableComponent::OwnableTwoStepImpl<ContractState>;
impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;

#[abi(embed_v0)]
impl AccessControlImpl =
Expand Down Expand Up @@ -50,7 +52,7 @@ mod AccessController {
}
}

#[external(v0)]
#[abi(embed_v0)]
impl UpgradeableImpl of IUpgradeable<ContractState> {
fn upgrade(ref self: ContractState, new_impl: ClassHash) {
self.ownable.assert_only_owner();
Expand Down
258 changes: 217 additions & 41 deletions contracts/src/account.cairo
Original file line number Diff line number Diff line change
@@ -1,57 +1,233 @@
// copied from https://github.com/OpenZeppelin/cairo-contracts/blob/v0.8.1/src/presets/account.cairo
// copied from https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.9.0/src/access/ownable/ownable.cairo

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts for Cairo v0.8.1 (presets/account.cairo)
// OpenZeppelin Contracts for Cairo v0.9.0 (access/ownable/ownable.cairo)

/// # Account Preset
/// # Ownable Component
///
/// OpenZeppelin's basic account which can change its public key and declare, deploy, or call contracts.
#[starknet::contract(account)]
mod Account {
use openzeppelin::account::AccountComponent;
use openzeppelin::introspection::src5::SRC5Component;

component!(path: AccountComponent, storage: account, event: AccountEvent);
component!(path: SRC5Component, storage: src5, event: SRC5Event);

// Account
#[abi(embed_v0)]
impl SRC6Impl = AccountComponent::SRC6Impl<ContractState>;
#[abi(embed_v0)]
impl SRC6CamelOnlyImpl = AccountComponent::SRC6CamelOnlyImpl<ContractState>;
#[abi(embed_v0)]
impl PublicKeyImpl = AccountComponent::PublicKeyImpl<ContractState>;
#[abi(embed_v0)]
impl PublicKeyCamelImpl = AccountComponent::PublicKeyCamelImpl<ContractState>;
#[abi(embed_v0)]
impl DeclarerImpl = AccountComponent::DeclarerImpl<ContractState>;
#[abi(embed_v0)]
impl DeployableImpl = AccountComponent::DeployableImpl<ContractState>;
impl AccountInternalImpl = AccountComponent::InternalImpl<ContractState>;

// SRC5
#[abi(embed_v0)]
impl SRC5Impl = SRC5Component::SRC5Impl<ContractState>;
/// The Ownable component provides a basic access control mechanism, where
/// there is an account (an owner) that can be granted exclusive access to
/// specific functions.
///
/// The initial owner can be set by using the `initializer` function in
/// construction time. This can later be changed with `transfer_ownership`.
///
/// The component also offers functionality for a two-step ownership
/// transfer where the new owner first has to accept their ownership to
/// finalize the transfer.
#[starknet::component]
mod OwnableComponent {
use openzeppelin::access::ownable::interface;
use starknet::ContractAddress;
use starknet::get_caller_address;

#[storage]
struct Storage {
#[substorage(v0)]
account: AccountComponent::Storage,
#[substorage(v0)]
src5: SRC5Component::Storage
Ownable_owner: ContractAddress,
Ownable_pending_owner: ContractAddress
}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
#[flat]
AccountEvent: AccountComponent::Event,
#[flat]
SRC5Event: SRC5Component::Event
OwnershipTransferred: OwnershipTransferred,
OwnershipTransferStarted: OwnershipTransferStarted
}

#[derive(Drop, starknet::Event)]
struct OwnershipTransferred {
#[key]
previous_owner: ContractAddress,
#[key]
new_owner: ContractAddress,
}

#[derive(Drop, starknet::Event)]
struct OwnershipTransferStarted {
#[key]
previous_owner: ContractAddress,
#[key]
new_owner: ContractAddress,
}

mod Errors {
const NOT_OWNER: felt252 = 'Caller is not the owner';
const NOT_PENDING_OWNER: felt252 = 'Caller is not the pending owner';
const ZERO_ADDRESS_CALLER: felt252 = 'Caller is the zero address';
const ZERO_ADDRESS_OWNER: felt252 = 'New owner is the zero address';
}

#[embeddable_as(OwnableImpl)]
impl Ownable<
TContractState, +HasComponent<TContractState>
> of interface::IOwnable<ComponentState<TContractState>> {
/// Returns the address of the current owner.
fn owner(self: @ComponentState<TContractState>) -> ContractAddress {
self.Ownable_owner.read()
}

/// Transfers ownership of the contract to a new address.
///
/// Requirements:
///
/// - `new_owner` is not the zero address.
/// - The caller is the contract owner.
///
/// Emits an `OwnershipTransferred` event.
fn transfer_ownership(
ref self: ComponentState<TContractState>, new_owner: ContractAddress
) {
assert(!new_owner.is_zero(), Errors::ZERO_ADDRESS_OWNER);
self.assert_only_owner();
self._transfer_ownership(new_owner);
}

/// Leaves the contract without owner. It will not be possible to call `assert_only_owner`
/// functions anymore. Can only be called by the current owner.
///
/// Requirements:
///
/// - The caller is the contract owner.
///
/// Emits an `OwnershipTransferred` event.
fn renounce_ownership(ref self: ComponentState<TContractState>) {
self.assert_only_owner();
self._transfer_ownership(Zeroable::zero());
}
}

/// Adds support for two step ownership transfer.
#[embeddable_as(OwnableTwoStepImpl)]
impl OwnableTwoStep<
TContractState, +HasComponent<TContractState>
> of interface::IOwnableTwoStep<ComponentState<TContractState>> {
/// Returns the address of the current owner.
fn owner(self: @ComponentState<TContractState>) -> ContractAddress {
self.Ownable_owner.read()
}

/// Returns the address of the pending owner.
fn pending_owner(self: @ComponentState<TContractState>) -> ContractAddress {
self.Ownable_pending_owner.read()
}

/// Finishes the two-step ownership transfer process by accepting the ownership.
/// Can only be called by the pending owner.
fn accept_ownership(ref self: ComponentState<TContractState>) {
let caller = get_caller_address();
let pending_owner = self.Ownable_pending_owner.read();
assert(caller == pending_owner, Errors::NOT_PENDING_OWNER);
self._accept_ownership();
}

/// Starts the two-step ownership transfer process by setting the pending owner.
fn transfer_ownership(
ref self: ComponentState<TContractState>, new_owner: ContractAddress
) {
self.assert_only_owner();
self._propose_owner(new_owner);
}

/// Leaves the contract without owner. It will not be possible to call `assert_only_owner`
/// functions anymore. Can only be called by the current owner.
fn renounce_ownership(ref self: ComponentState<TContractState>) {
Ownable::renounce_ownership(ref self);
}
}

/// Adds camelCase support for `IOwnable`.
#[embeddable_as(OwnableCamelOnlyImpl)]
impl OwnableCamelOnly<
TContractState, +HasComponent<TContractState>
> of interface::IOwnableCamelOnly<ComponentState<TContractState>> {
fn transferOwnership(ref self: ComponentState<TContractState>, newOwner: ContractAddress) {
Ownable::transfer_ownership(ref self, newOwner);
}

fn renounceOwnership(ref self: ComponentState<TContractState>) {
Ownable::renounce_ownership(ref self);
}
}

/// Adds camelCase support for `IOwnableTwoStep`.
#[embeddable_as(OwnableTwoStepCamelOnlyImpl)]
impl OwnableTwoStepCamelOnly<
TContractState, +HasComponent<TContractState>
> of interface::IOwnableTwoStepCamelOnly<ComponentState<TContractState>> {
fn pendingOwner(self: @ComponentState<TContractState>) -> ContractAddress {
OwnableTwoStep::pending_owner(self)
}

fn acceptOwnership(ref self: ComponentState<TContractState>) {
self.accept_ownership();
}

fn transferOwnership(ref self: ComponentState<TContractState>, newOwner: ContractAddress) {
OwnableTwoStep::transfer_ownership(ref self, newOwner);
}

fn renounceOwnership(ref self: ComponentState<TContractState>) {
OwnableTwoStep::renounce_ownership(ref self);
}
}

#[constructor]
fn constructor(ref self: ContractState, public_key: felt252) {
self.account.initializer(public_key);
#[generate_trait]
impl InternalImpl<
TContractState, +HasComponent<TContractState>
> of InternalTrait<TContractState> {
/// Sets the contract's initial owner.
///
/// This function should be called at construction time.
fn initializer(ref self: ComponentState<TContractState>, owner: ContractAddress) {
self._transfer_ownership(owner);
}

/// Panics if called by any account other than the owner. Use this
/// to restrict access to certain functions to the owner.
fn assert_only_owner(self: @ComponentState<TContractState>) {
let owner = self.Ownable_owner.read();
let caller = get_caller_address();
assert(!caller.is_zero(), Errors::ZERO_ADDRESS_CALLER);
assert(caller == owner, Errors::NOT_OWNER);
}

/// Transfers ownership to the pending owner.
///
/// Internal function without access restriction.
fn _accept_ownership(ref self: ComponentState<TContractState>) {
let pending_owner = self.Ownable_pending_owner.read();
self.Ownable_pending_owner.write(Zeroable::zero());
self._transfer_ownership(pending_owner);
}

/// Sets a new pending owner.
///
/// Internal function without access restriction.
fn _propose_owner(ref self: ComponentState<TContractState>, new_owner: ContractAddress) {
let previous_owner = self.Ownable_owner.read();
self.Ownable_pending_owner.write(new_owner);
self
.emit(
OwnershipTransferStarted {
previous_owner: previous_owner, new_owner: new_owner
}
);
}

/// Transfers ownership of the contract to a new address.
///
/// Internal function without access restriction.
///
/// Emits an `OwnershipTransferred` event.
fn _transfer_ownership(
ref self: ComponentState<TContractState>, new_owner: ContractAddress
) {
let previous_owner: ContractAddress = self.Ownable_owner.read();
self.Ownable_owner.write(new_owner);
self
.emit(
OwnershipTransferred { previous_owner: previous_owner, new_owner: new_owner }
);
}
}
}
12 changes: 7 additions & 5 deletions contracts/src/emergency/sequencer_uptime_feed.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ mod SequencerUptimeFeed {
use option::OptionTrait;
use zeroable::Zeroable;

use chainlink::libraries::ownable::{OwnableComponent, IOwnable};
use openzeppelin::access::ownable::ownable::OwnableComponent;

// use chainlink::libraries::ownable::{OwnableComponent, IOwnable};
use chainlink::libraries::access_control::{AccessControlComponent, IAccessController};
use chainlink::libraries::access_control::AccessControlComponent::InternalTrait as AccessControlInternalTrait;
use chainlink::libraries::type_and_version::ITypeAndVersion;
Expand All @@ -40,7 +42,7 @@ mod SequencerUptimeFeed {
component!(path: AccessControlComponent, storage: access_control, event: AccessControlEvent);

#[abi(embed_v0)]
impl OwnableImpl = OwnableComponent::OwnableImpl<ContractState>;
impl OwnableImpl = OwnableComponent::OwnableTwoStepImpl<ContractState>;
impl OwnableInternalImpl = OwnableComponent::InternalImpl<ContractState>;

#[abi(embed_v0)]
Expand Down Expand Up @@ -116,7 +118,7 @@ mod SequencerUptimeFeed {
}
}

#[external(v0)]
#[abi(embed_v0)]
impl AggregatorImpl of IAggregator<ContractState> {
fn latest_round_data(self: @ContractState) -> Round {
self._require_read_access();
Expand Down Expand Up @@ -189,7 +191,7 @@ mod SequencerUptimeFeed {
}
}

#[external(v0)]
#[abi(embed_v0)]
impl SequencerUptimeFeedImpl of super::ISequencerUptimeFeed<ContractState> {
fn set_l1_sender(ref self: ContractState, address: EthAddress) {
self.ownable.assert_only_owner();
Expand Down Expand Up @@ -220,7 +222,7 @@ mod SequencerUptimeFeed {
/// Upgradeable
///
#[external(v0)]
#[abi(embed_v0)]
fn upgrade(ref self: ContractState, new_impl: ClassHash) {
self.ownable.assert_only_owner();
Upgradeable::upgrade(new_impl)
Expand Down
1 change: 1 addition & 0 deletions contracts/src/libraries.cairo
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod ownable;
mod zownable;
mod access_control;
mod token;
mod upgradeable;
Expand Down
Loading

0 comments on commit 08fdb4a

Please sign in to comment.