-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #16 from khaeljy/khaeljy/issue15
Add positions list
- Loading branch information
Showing
14 changed files
with
436 additions
and
253 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
target | ||
.env | ||
accounts | ||
accounts/*.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Code generated by scarb DO NOT EDIT. | ||
version = 1 | ||
|
||
[[package]] | ||
name = "openzeppelin" | ||
version = "0.8.0" | ||
source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.8.0#c23e8e96de60e6e3159b1ff8591a1187269c0eb7" | ||
|
||
[[package]] | ||
name = "swappy" | ||
version = "0.0.1" | ||
dependencies = [ | ||
"openzeppelin", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# Create a new signer | ||
``` | ||
starkli signer keystore new accounts/keystore.json | ||
export STARKNET_KEYSTORE=accounts/keystore.json | ||
``` | ||
|
||
# Create the deployer account | ||
``` | ||
starkli account oz init accounts/deployer.json | ||
starkli account deploy accounts/deployer.json | ||
``` | ||
|
||
# Declare Swappy Account Contract | ||
``` | ||
starkli declare target/dev/swappy_Account.contract_class.json --account accounts/deployer.json | ||
# 0x03dd8bbd25d0807d830cc78f3aef5e759c186c8f91efe1fcf3531132fdcade4b | ||
``` | ||
|
||
# Create a swappy account | ||
``` | ||
starkli account oz init accounts/swappy.json | ||
``` | ||
> update class_hash | ||
``` | ||
starkli account deploy accounts/swappy.json | ||
``` | ||
|
||
# Deploy Position Manager Contract | ||
``` | ||
starkli declare target/dev/swappy_PositionManager.contract_class.json --account accounts/deployer.json | ||
# 0x0303b3c6adfb5015a09bce62b23428bb3e3b4bca3726a27919ae78763b5e993a | ||
starkli deploy 0x0303b3c6adfb5015a09bce62b23428bb3e3b4bca3726a27919ae78763b5e993a 0x0 --account accounts/deployer.json | ||
# 0x0097ab8a6dc7760a687caaffa7101611b20babda533ce40b3cac94fb1926355e | ||
``` | ||
|
||
# Get last position ID | ||
``` | ||
starkli call 0x0097ab8a6dc7760a687caaffa7101611b20babda533ce40b3cac94fb1926355e get_last_id | ||
``` | ||
|
||
# create position | ||
``` | ||
starkli invoke 0x0097ab8a6dc7760a687caaffa7101611b20babda533ce40b3cac94fb1926355e create_position 0x1 0x2 u256:1 u256:1 --account accounts/swappy.json | ||
``` | ||
|
||
# Pause position | ||
``` | ||
starkli invoke 0x0097ab8a6dc7760a687caaffa7101611b20babda533ce40b3cac94fb1926355e pause_position [POSITION_ID] --account accounts/swappy.json | ||
``` | ||
|
||
# Resume position | ||
``` | ||
starkli invoke 0x0097ab8a6dc7760a687caaffa7101611b20babda533ce40b3cac94fb1926355e resume_position [POSITION_ID] --account accounts/swappy.json | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,244 +1,50 @@ | ||
use array::ArrayTrait; | ||
use array::SpanTrait; | ||
use option::OptionTrait; | ||
use serde::Serde; | ||
use starknet::ContractAddress; | ||
use starknet::account::Call; | ||
|
||
const TRANSACTION_VERSION: felt252 = 1; | ||
|
||
// 2**128 + TRANSACTION_VERSION | ||
const QUERY_VERSION: felt252 = 340282366920938463463374607431768211457; | ||
|
||
trait PublicKeyTrait<TState> { | ||
fn set_public_key(ref self: TState, new_public_key: felt252); | ||
fn get_public_key(self: @TState) -> felt252; | ||
} | ||
|
||
trait PublicKeyCamelTrait<TState> { | ||
fn setPublicKey(ref self: TState, newPublicKey: felt252); | ||
fn getPublicKey(self: @TState) -> felt252; | ||
} | ||
|
||
#[starknet::contract] | ||
mod Account { | ||
use array::ArrayTrait; | ||
use array::SpanTrait; | ||
use box::BoxTrait; | ||
use ecdsa::check_ecdsa_signature; | ||
|
||
use openzeppelin::account::interface; | ||
use openzeppelin::introspection::interface::ISRC5; | ||
use openzeppelin::introspection::interface::ISRC5Camel; | ||
use openzeppelin::introspection::src5::SRC5; | ||
use option::OptionTrait; | ||
use starknet::get_caller_address; | ||
use starknet::get_contract_address; | ||
use starknet::get_tx_info; | ||
|
||
use super::Call; | ||
use super::QUERY_VERSION; | ||
use super::TRANSACTION_VERSION; | ||
use zeroable::Zeroable; | ||
|
||
use swappy::account::error::AccountError; | ||
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>; | ||
|
||
#[storage] | ||
struct Storage { | ||
public_key: felt252 | ||
#[substorage(v0)] | ||
account: AccountComponent::Storage, | ||
#[substorage(v0)] | ||
src5: SRC5Component::Storage | ||
} | ||
|
||
#[event] | ||
#[derive(Drop, starknet::Event)] | ||
enum Event { | ||
OwnerAdded: OwnerAdded, | ||
OwnerRemoved: OwnerRemoved, | ||
} | ||
|
||
#[derive(Drop, starknet::Event)] | ||
struct OwnerAdded { | ||
new_owner_guid: felt252 | ||
} | ||
|
||
#[derive(Drop, starknet::Event)] | ||
struct OwnerRemoved { | ||
removed_owner_guid: felt252 | ||
#[flat] | ||
AccountEvent: AccountComponent::Event, | ||
#[flat] | ||
SRC5Event: SRC5Component::Event | ||
} | ||
|
||
#[constructor] | ||
fn constructor(ref self: ContractState, _public_key: felt252) { | ||
self.initializer(_public_key); | ||
} | ||
|
||
// | ||
// External | ||
// | ||
|
||
#[external(v0)] | ||
impl SRC6Impl of interface::ISRC6<ContractState> { | ||
fn __execute__(self: @ContractState, mut calls: Array<Call>) -> Array<Span<felt252>> { | ||
// Avoid calls from other contracts | ||
let sender = get_caller_address(); | ||
assert(sender.is_zero(), AccountError::INVALID_CALLER); | ||
|
||
// Check tx version | ||
let tx_info = get_tx_info().unbox(); | ||
let version = tx_info.version; | ||
if version != TRANSACTION_VERSION { | ||
assert(version == QUERY_VERSION, AccountError::INVALID_TX_VERSION); | ||
} | ||
|
||
_execute_calls(calls) | ||
} | ||
|
||
fn __validate__(self: @ContractState, mut calls: Array<Call>) -> felt252 { | ||
self.validate_transaction() | ||
} | ||
|
||
fn is_valid_signature( | ||
self: @ContractState, hash: felt252, signature: Array<felt252> | ||
) -> felt252 { | ||
if self._is_valid_signature(hash, signature.span()) { | ||
starknet::VALIDATED | ||
} else { | ||
0 | ||
} | ||
} | ||
} | ||
|
||
#[external(v0)] | ||
impl SRC6CamelOnlyImpl of interface::ISRC6CamelOnly<ContractState> { | ||
fn isValidSignature( | ||
self: @ContractState, hash: felt252, signature: Array<felt252> | ||
) -> felt252 { | ||
SRC6Impl::is_valid_signature(self, hash, signature) | ||
} | ||
} | ||
|
||
#[external(v0)] | ||
impl DeclarerImpl of interface::IDeclarer<ContractState> { | ||
fn __validate_declare__(self: @ContractState, class_hash: felt252) -> felt252 { | ||
self.validate_transaction() | ||
} | ||
} | ||
|
||
#[external(v0)] | ||
impl SRC5Impl of ISRC5<ContractState> { | ||
fn supports_interface(self: @ContractState, interface_id: felt252) -> bool { | ||
let unsafe_state = SRC5::unsafe_new_contract_state(); | ||
SRC5::SRC5Impl::supports_interface(@unsafe_state, interface_id) | ||
} | ||
} | ||
|
||
#[external(v0)] | ||
impl SRC5CamelImpl of ISRC5Camel<ContractState> { | ||
fn supportsInterface(self: @ContractState, interfaceId: felt252) -> bool { | ||
let unsafe_state = SRC5::unsafe_new_contract_state(); | ||
SRC5::SRC5CamelImpl::supportsInterface(@unsafe_state, interfaceId) | ||
} | ||
} | ||
|
||
#[external(v0)] | ||
impl PublicKeyImpl of super::PublicKeyTrait<ContractState> { | ||
fn get_public_key(self: @ContractState) -> felt252 { | ||
self.public_key.read() | ||
} | ||
|
||
fn set_public_key(ref self: ContractState, new_public_key: felt252) { | ||
assert_only_self(); | ||
self.emit(OwnerRemoved { removed_owner_guid: self.public_key.read() }); | ||
self._set_public_key(new_public_key); | ||
} | ||
} | ||
|
||
#[external(v0)] | ||
impl PublicKeyCamelImpl of super::PublicKeyCamelTrait<ContractState> { | ||
fn getPublicKey(self: @ContractState) -> felt252 { | ||
self.public_key.read() | ||
} | ||
|
||
fn setPublicKey(ref self: ContractState, newPublicKey: felt252) { | ||
PublicKeyImpl::set_public_key(ref self, newPublicKey); | ||
} | ||
} | ||
|
||
#[external(v0)] | ||
fn __validate_deploy__( | ||
self: @ContractState, | ||
class_hash: felt252, | ||
contract_address_salt: felt252, | ||
_public_key: felt252 | ||
) -> felt252 { | ||
self.validate_transaction() | ||
} | ||
|
||
// | ||
// Internal | ||
// | ||
|
||
#[generate_trait] | ||
impl InternalImpl of InternalTrait { | ||
fn initializer(ref self: ContractState, _public_key: felt252) { | ||
let mut unsafe_state = SRC5::unsafe_new_contract_state(); | ||
SRC5::InternalImpl::register_interface(ref unsafe_state, interface::ISRC6_ID); | ||
self._set_public_key(_public_key); | ||
} | ||
|
||
fn validate_transaction(self: @ContractState) -> felt252 { | ||
let tx_info = get_tx_info().unbox(); | ||
let tx_hash = tx_info.transaction_hash; | ||
let signature = tx_info.signature; | ||
assert(self._is_valid_signature(tx_hash, signature), AccountError::INVALID_SIGNATURE); | ||
starknet::VALIDATED | ||
} | ||
|
||
fn _set_public_key(ref self: ContractState, new_public_key: felt252) { | ||
self.public_key.write(new_public_key); | ||
self.emit(OwnerAdded { new_owner_guid: new_public_key }); | ||
} | ||
|
||
fn _is_valid_signature( | ||
self: @ContractState, hash: felt252, signature: Span<felt252> | ||
) -> bool { | ||
let valid_length = signature.len() == 2_u32; | ||
|
||
if valid_length { | ||
check_ecdsa_signature( | ||
hash, self.public_key.read(), *signature.at(0_u32), *signature.at(1_u32) | ||
) | ||
} else { | ||
false | ||
} | ||
} | ||
} | ||
|
||
#[internal] | ||
fn assert_only_self() { | ||
let caller = get_caller_address(); | ||
let self = get_contract_address(); | ||
assert(self == caller, AccountError::UNAUTHORIZED); | ||
} | ||
|
||
#[internal] | ||
fn _execute_calls(mut calls: Array<Call>) -> Array<Span<felt252>> { | ||
let mut res = ArrayTrait::new(); | ||
loop { | ||
match calls.pop_front() { | ||
Option::Some(call) => { | ||
let _res = _execute_single_call(call); | ||
res.append(_res); | ||
}, | ||
Option::None(_) => { | ||
break (); | ||
}, | ||
}; | ||
}; | ||
res | ||
} | ||
|
||
#[internal] | ||
fn _execute_single_call(call: Call) -> Span<felt252> { | ||
let Call{to, selector, calldata } = call; | ||
starknet::call_contract_syscall(to, selector, calldata.span()).unwrap() | ||
fn constructor(ref self: ContractState, public_key: felt252) { | ||
self.account.initializer(public_key); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
mod AccountError { | ||
const INVALID_CALLER: felt252 = 'Account: invalid caller'; | ||
const INVALID_TX_VERSION: felt252 = 'Account: invalid tx version'; | ||
const INVALID_SIGNATURE: felt252 = 'Account: invalid signature'; | ||
const UNAUTHORIZED: felt252 = 'Account: unauthorized'; | ||
mod AccountError { // const INVALID_CALLER: felt252 = 'Account: invalid caller'; | ||
// const INVALID_TX_VERSION: felt252 = 'Account: invalid tx version'; | ||
// const INVALID_SIGNATURE: felt252 = 'Account: invalid signature'; | ||
// const UNAUTHORIZED: felt252 = 'Account: unauthorized'; | ||
// const POSITION_NOT_FOUND: felt252 = 'Account: position not found'; | ||
} |
Oops, something went wrong.