-
Notifications
You must be signed in to change notification settings - Fork 104
Base precompile code between connectors #73
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,187 @@ | ||
| use evm::{Context, ExitError, ExitSucceed}; | ||
|
|
||
| use super::{Precompile, PrecompileResult}; | ||
| use crate::prelude::{String, Vec, U256, ToString}; | ||
| use crate::sdk; | ||
| use crate::types::{AccountId}; | ||
|
|
||
| mod costs { | ||
| use crate::types::Gas; | ||
|
|
||
| // TODO(#51): Determine the correct amount of gas | ||
| pub(super) const EXIT_TO_NEAR_GAS: Gas = 0; | ||
|
|
||
| // TODO(#51): Determine the correct amount of gas | ||
| pub(super) const EXIT_TO_ETHEREUM_GAS: Gas = 0; | ||
|
|
||
| // TODO(#51): Determine the correct amount of gas | ||
| pub(super) const FT_TRANSFER_GAS: Gas = 100_000_000_000_000; | ||
|
|
||
| // TODO(#51): Determine the correct amount of gas | ||
| pub(super) const WITHDRAWAL_GAS: Gas = 100_000_000_000_000; | ||
| } | ||
|
|
||
| /// Get the current nep141 token associated with the current erc20 token. | ||
| /// This will fail is none is associated. | ||
| fn get_nep141_from_erc20(_erc20_token: &[u8]) -> AccountId { | ||
| // TODO: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where it will TODO? If not planned now we should create an issue.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it is done in pr #51 , didnt remove for it to compile |
||
| "".to_string() | ||
| } | ||
|
|
||
| pub struct ExitToNear; //TransferEthToNear | ||
|
|
||
| impl Precompile for ExitToNear { | ||
| fn required_gas(_input: &[u8]) -> Result<u64, ExitError> { | ||
| Ok(costs::EXIT_TO_NEAR_GAS) | ||
| } | ||
|
|
||
| fn run(input: &[u8], target_gas: u64, context: &Context) -> PrecompileResult { | ||
| if Self::required_gas(input)? > target_gas { | ||
| return Err(ExitError::OutOfGas); | ||
| } | ||
|
|
||
| let (nep141_address, args) = if context.apparent_value != U256::from(0) { | ||
| // ETH transfer | ||
| // | ||
| // Input slice format: | ||
| // recipient_account_id (bytes) - the NEAR recipient account which will receive NEP-141 ETH tokens | ||
|
|
||
| ( | ||
| String::from_utf8(sdk::current_account_id()).unwrap(), | ||
| crate::prelude::format!( | ||
| r#"{{"receiver_id": "{}", "amount": "{}", "memo": null}}"#, | ||
| String::from_utf8(input.to_vec()).unwrap(), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please, add a check to validate the |
||
| context.apparent_value.as_u128() | ||
| ), | ||
| ) | ||
| } else { | ||
| // ERC20 transfer | ||
| // | ||
| // This precompile branch is expected to be called from the ERC20 burn function\ | ||
| // | ||
| // Input slice format: | ||
| // amount (U256 le bytes) - the amount that was burned | ||
| // recipient_account_id (bytes) - the NEAR recipient account which will receive NEP-141 tokens | ||
|
|
||
| let nep141_address = get_nep141_from_erc20(context.caller.as_bytes()); | ||
|
|
||
| let mut input_mut = input; | ||
| let amount = U256::from_big_endian(&input_mut[..32]).as_u128(); | ||
| input_mut = &input_mut[32..]; | ||
| let receiver_account_id: AccountId = String::from_utf8(input_mut.to_vec()).unwrap(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The same thing about the |
||
| ( | ||
| nep141_address, | ||
| crate::prelude::format!( | ||
| r#"{{"receiver_id": "{}", "amount": "{}", "memo": null}}"#, | ||
| receiver_account_id, | ||
| amount | ||
| ), | ||
| ) | ||
| }; | ||
|
|
||
| let promise0 = sdk::promise_create( | ||
| nep141_address, | ||
| b"ft_transfer", | ||
| args.as_bytes(), | ||
| 1, | ||
| costs::FT_TRANSFER_GAS, | ||
| ); | ||
|
|
||
| sdk::promise_return(promise0); | ||
|
|
||
| Ok((ExitSucceed::Returned, Vec::new(), 0)) | ||
| } | ||
| } | ||
|
|
||
| pub struct ExitToEthereum; | ||
|
|
||
| impl Precompile for ExitToEthereum { | ||
| fn required_gas(_input: &[u8]) -> Result<u64, ExitError> { | ||
| Ok(costs::EXIT_TO_ETHEREUM_GAS) | ||
| } | ||
|
|
||
| fn run(input: &[u8], target_gas: u64, context: &Context) -> PrecompileResult { | ||
| if Self::required_gas(input)? > target_gas { | ||
| return Err(ExitError::OutOfGas); | ||
| } | ||
|
|
||
| let (nep141_address, serialized_args) = if context.apparent_value != U256::from(0) { | ||
| // ETH transfer | ||
| // | ||
| // Input slice format: | ||
| // eth_recipient (20 bytes) - the address of recipient which will receive ETH on Ethereum | ||
|
|
||
| let eth_recipient: String = hex::encode(input); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please, check the |
||
|
|
||
| ( | ||
| String::from_utf8(sdk::current_account_id()).unwrap(), | ||
| crate::prelude::format!( | ||
| r#"{{"amount": "{}", "recipient": "{}"}}"#, | ||
| context.apparent_value.as_u128(), | ||
| eth_recipient | ||
| ), | ||
| ) | ||
| } else { | ||
| // ERC-20 transfer | ||
| // | ||
| // This precompile branch is expected to be called from the ERC20 withdraw function | ||
| // (or burn function with some flag provided that this is expected to be withdrawn) | ||
| // | ||
| // Input slice format: | ||
| // amount (U256 le bytes) - the amount that was burned | ||
| // eth_recipient (20 bytes) - the address of recipient which will receive ETH on Ethereum | ||
|
|
||
| let nep141_address = get_nep141_from_erc20(context.caller.as_bytes()); | ||
|
|
||
| let mut input_mut = input; | ||
|
|
||
| let amount = U256::from_big_endian(&input_mut[..32]).as_u128(); | ||
| input_mut = &input_mut[32..]; | ||
|
|
||
| assert_eq!(input_mut.len(), 20); | ||
|
|
||
| // Parse ethereum address in hex | ||
| let eth_recipient: String = hex::encode(input_mut.to_vec()); | ||
|
|
||
| ( | ||
| nep141_address, | ||
| crate::prelude::format!( | ||
| r#"{{"amount": "{}", "recipient": "{}"}}"#, | ||
| amount, | ||
| eth_recipient | ||
| ), | ||
| ) | ||
| }; | ||
|
|
||
| let promise0 = sdk::promise_create( | ||
| nep141_address, | ||
| b"withdraw", | ||
| serialized_args.as_bytes(), | ||
| 1, | ||
| costs::WITHDRAWAL_GAS, | ||
| ); | ||
|
|
||
| sdk::promise_return(promise0); | ||
|
|
||
| Ok((ExitSucceed::Returned, Vec::new(), 0)) | ||
| } | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::*; | ||
| use crate::precompiles::{EXIT_TO_ETHEREUM_ID, EXIT_TO_NEAR_ID}; | ||
| use crate::types::near_account_to_evm_address; | ||
|
|
||
| #[test] | ||
| fn test_precompile_id() { | ||
| assert_eq!( | ||
| EXIT_TO_ETHEREUM_ID, | ||
| near_account_to_evm_address("exitToEthereum".as_bytes()).to_low_u64_be() | ||
| ); | ||
| assert_eq!( | ||
| EXIT_TO_NEAR_ID, | ||
| near_account_to_evm_address("exitToNear".as_bytes()).to_low_u64_be() | ||
| ); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,8 +15,8 @@ mod exports { | |
| // # Context API # | ||
| // ############### | ||
| pub(crate) fn current_account_id(register_id: u64); | ||
| fn signer_account_id(register_id: u64); | ||
| fn signer_account_pk(register_id: u64); | ||
| pub(crate) fn signer_account_id(register_id: u64); | ||
| pub(crate) fn signer_account_pk(register_id: u64); | ||
| pub(crate) fn predecessor_account_id(register_id: u64); | ||
| pub(crate) fn input(register_id: u64); | ||
| // TODO #1903 fn block_height() -> u64; | ||
|
|
@@ -278,6 +278,26 @@ pub fn predecessor_account_id() -> Vec<u8> { | |
| } | ||
| } | ||
|
|
||
| #[allow(dead_code)] | ||
| pub fn signer_account_id() -> Vec<u8> { | ||
| unsafe { | ||
| exports::signer_account_id(1); | ||
| let bytes: Vec<u8> = vec![0u8; exports::register_len(1) as usize]; | ||
| exports::read_register(1, bytes.as_ptr() as *const u64 as u64); | ||
| bytes | ||
| } | ||
| } | ||
|
|
||
| #[allow(dead_code)] | ||
| pub fn signer_account_pk() -> Vec<u8> { | ||
| unsafe { | ||
| exports::signer_account_pk(1); | ||
| let bytes: Vec<u8> = vec![0u8; exports::register_len(1) as usize]; | ||
| exports::read_register(1, bytes.as_ptr() as *const u64 as u64); | ||
| bytes | ||
| } | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need these in the current PR?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We dont! |
||
|
|
||
| /// Calls environment sha256 on given input. | ||
| #[allow(dead_code)] | ||
| pub fn sha256(input: &[u8]) -> H256 { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| use crate::prelude::{Address, String, Vec, H256, U256}; | ||
| use borsh::{BorshDeserialize, BorshSerialize}; | ||
|
|
||
| #[cfg(not(feature = "contract"))] | ||
| use sha3::{Digest, Keccak256}; | ||
|
|
@@ -10,6 +11,11 @@ pub type AccountId = String; | |
| pub type RawAddress = [u8; 20]; | ||
| pub type RawU256 = [u8; 32]; // Little-endian large integer type. | ||
| pub type RawH256 = [u8; 32]; // Unformatted binary data of fixed length. | ||
| pub type Gas = u64; | ||
| pub type Balance = u128; | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just notice that we have the same type et
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's have it here since they are common to both |
||
| #[derive(BorshSerialize, BorshDeserialize)] | ||
| pub struct U128(pub u128); | ||
|
|
||
| pub const STORAGE_PRICE_PER_BYTE: u128 = 100_000_000_000_000_000_000; // 1e20yN, 0.0001N | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.