diff --git a/README.md b/README.md index a2b0ed4b..b761a5c8 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ - [Whitelist Contract](./whitelist/) - [Staking Pool Factory](./staking-pool-factory/) - [Multisig contract](./multisig/) +- [Exchange Deposit Receiver](./exchange-deposit-receiver) **Note**: observe the usage of the file `rust-toolchain` in the project root. This file contains toolchain information for nightly, while the `build.sh` scripts in respective contract subdirectories may override this with `cargo +stable`. Refer to the documentation on [the toolchain file and override precedence](https://github.com/rust-lang/rustup#the-toolchain-file). Keep in mind that the build scripts may use `stable` while `cargo test` may use nightly. @@ -65,7 +66,7 @@ const result = account.signAndSendTransaction( contractName, [ nearAPI.transactions.createAccount(), - nearAPI.transactions.transfer("100000000000000000000000000"), + nearAPI.transactions.transfer("100000000000000000000000000"), nearAPI.transactions.deployContract(fs.readFileSync("res/lockup_contract.wasm")), nearAPI.transactions.functionCall("new", Buffer.from(JSON.stringify(newArgs)), 100000000000000, "0"), ]); diff --git a/exchange-deposit-receiver/Cargo.lock b/exchange-deposit-receiver/Cargo.lock new file mode 100644 index 00000000..1d0c8dba --- /dev/null +++ b/exchange-deposit-receiver/Cargo.lock @@ -0,0 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "exchange-deposit-receiver" +version = "0.1.0" diff --git a/exchange-deposit-receiver/Cargo.toml b/exchange-deposit-receiver/Cargo.toml new file mode 100644 index 00000000..8bd79845 --- /dev/null +++ b/exchange-deposit-receiver/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "exchange-deposit-receiver" +version = "0.1.0" +authors = ["Near Inc "] +edition = "2018" +publish = false + +[lib] +crate-type = ["cdylib", "rlib"] + +[profile.release] +codegen-units = 1 +# Tell `rustc` to optimize for small code size. +opt-level = "s" +lto = true +debug = false +panic = "abort" diff --git a/exchange-deposit-receiver/README.md b/exchange-deposit-receiver/README.md new file mode 100644 index 00000000..903fa28f --- /dev/null +++ b/exchange-deposit-receiver/README.md @@ -0,0 +1,54 @@ +# Exchange deposit receiver + +## Background + +Exchanges usually creates an new account for a user to deposit their tokens. On NEAR, the account can't be created +without a deposit to cover the occupied storage. It cost tokens on exchange side to create such account before the user +can deposit tokens. So if the user doesn't deposit tokens to the account, the exchange spent tokens on the creation of +the account. + +To avoid creating the account before any tokens from the user are received, the exchanges can also receive tokens +directly into their hot wallet, but every deposit has to be marked to be able to properly attribute it to the owner. +It's usually done with an additional `memo` field in the transaction. NEAR doesn't support comments on the transfers. +But NEAR does have function calls and the ability to attach tokens with the function call. + +## Overview + +The goal of this contract is to provide a contract endpoint to be able to deposit tokens with a memo. + +### The process is the following: +- An exchange deploys this contract on their hot wallet account. The exchange also maintains the full access to this account by +having a full access key on this account. It allows exchange to withdraw tokens from this account. +- When a user wants to deposit tokens to their account on the exchange, the exchange generates a unique `` message for +a user. +- The user sends a specific transaction to the exchange's hot wallet account with a single action. +This action should be supported by the wallets and the lockup contract. +```rust +FunctionCall { + method_name: "exchange_deposit", + args: b"", + gas: ..., + deposit: , +} +``` +- The transaction gets executed and the exchange's hot wallet account receives the ``. +- Exchange monitors incoming transactions and sees that this deposit has been associated with the ``. +- The exchange can now attribute `` for the user's account by mapping it with the received ``. + +## Interface + +```rust +pub fn exchange_deposit(); +``` + +## API examples + +Send `10` NEAR tokens to the exchange account `coin_exchange` with memo `USER_123` from user `token_owner`. + +Command: + +```bash +near call coin_exchange exchange_deposit 'USER_123' --accountId=token_owner --amount=10 +``` + +NOTE: This command temporarily doesn't work due to near-cli assumption about JSON input format. See https://github.com/near/near-cli/issues/503 diff --git a/exchange-deposit-receiver/build.sh b/exchange-deposit-receiver/build.sh new file mode 100755 index 00000000..0dd60bbd --- /dev/null +++ b/exchange-deposit-receiver/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -e + +RUSTFLAGS='-C link-arg=-s' cargo +nightly build --target wasm32-unknown-unknown --release +cp target/wasm32-unknown-unknown/release/exchange_deposit_receiver.wasm ./res/ diff --git a/exchange-deposit-receiver/res/exchange_deposit_receiver.wasm b/exchange-deposit-receiver/res/exchange_deposit_receiver.wasm new file mode 100755 index 00000000..13ced211 Binary files /dev/null and b/exchange-deposit-receiver/res/exchange_deposit_receiver.wasm differ diff --git a/exchange-deposit-receiver/src/lib.rs b/exchange-deposit-receiver/src/lib.rs new file mode 100644 index 00000000..34857e9a --- /dev/null +++ b/exchange-deposit-receiver/src/lib.rs @@ -0,0 +1,14 @@ +#![no_std] +#![feature(core_intrinsics)] +#![allow(non_snake_case)] + +#[panic_handler] +#[no_mangle] +pub fn on_panic(_info: &::core::panic::PanicInfo) -> ! { + unsafe { + ::core::intrinsics::abort(); + } +} + +#[no_mangle] +pub fn exchange_deposit() {}