Skip to content

Commit

Permalink
1.0.2: USN contract released on the NEAR mainnet.
Browse files Browse the repository at this point in the history
  • Loading branch information
Usn Zorro committed Apr 25, 2022
0 parents commit 5b660dc
Show file tree
Hide file tree
Showing 39 changed files with 5,015 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .cargo/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[build]
rustflags = ["-C", "link-args=-s"]
38 changes: 38 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Publish release

on:
create:
tags:
- v*

jobs:
test:
uses: ./.github/workflows/test.yaml

release:
needs: test

runs-on: ubuntu-latest

container:
image: nearprotocol/contract-builder
options: --cap-add=SYS_PTRACE --security-opt seccomp=unconfined
env:
RUSTFLAGS: -C link-arg=-s

steps:
- uses: actions/checkout@v2
- name: Build
run: |
rustup toolchain install stable
rustup default stable
rustup target add wasm32-unknown-unknown
cargo build --target wasm32-unknown-unknown --profile testnet --features testnet
cargo build --target wasm32-unknown-unknown --profile mainnet --features mainnet
mv target/wasm32-unknown-unknown/mainnet/usn.wasm target/usn.mainnet.wasm
mv target/wasm32-unknown-unknown/testnet/usn.wasm target/usn.testnet.wasm
- name: Publish
uses: ncipollo/release-action@v1
with:
artifacts: "target/usn.*.wasm"
token: ${{ secrets.GITHUB_TOKEN }}
28 changes: 28 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Run tests

on:
workflow_call:

push:
branches:
- main

pull_request:
branches:
- main

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run Rustfmt
run: cargo fmt -- --check
- name: Run unit tests
run: cargo test --verbose
- name: Install NPM dependencies
run: npm install
- name: Build USN
run: npm run build
- name: Run integration tests on sandbox
run: npm run test
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
target/*
node_modules/*
package-lock.json
*.lock
*.iml
40 changes: 40 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
[package]
edition = "2018"
name = "usn"
version = "1.0.2"

[lib]
crate-type = ["cdylib", "rlib"]

[dependencies]
near-contract-standards = "=4.0.0-pre.7"
near-sdk = { version = "=4.0.0-pre.7", features = ["unstable"] }
uint = { version = "=0.9.0", default-features = false }
partial-min-max = "0.4.0"
easy-ml = "1.8.1"

[profile.release]
codegen-units = 1
debug = false
lto = true
opt-level = "s"
overflow-checks = true
panic = "abort"

[profile.sandbox]
inherits = "release"

[profile.testnet]
inherits = "release"

[profile.mainnet]
inherits = "release"

[features]
# Enables testnet configuration if expicitly stated.
# It makes the USN contract use a testnet oracle.
testnet = []

# Enables mainnet configuration if expicitly stated.
# It makes the USN contract use a main oracle.
mainnet = []
230 changes: 230 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
[![USN](https://github.com/binary-star-near/usn/actions/workflows/test.yaml/badge.svg?event=push)](https://github.com/binary-star-near/usn)

# USN

USN is a NEAR-native USD stable coin.

The contract implements fungible token API according to the following standards:

1. [NEP-141](https://nomicon.io/Standards/FungibleToken/Core) (ERC-20 fashioned)
2. [NEP-148](https://nomicon.io/Standards/FungibleToken/Metadata)
3. [Fungible Token Event](https://nomicon.io/Standards/FungibleToken/Event)

The specific part of the USN contract is `buy`/`sell` methods of NEAR/USD exchange with rates taken from the oracle ([priceoracle](https://github.com/NearDeFi/price-oracle/)).

# Contract Address

| Mainnet | Testnet |
| ------- | ------------ |
| usn | usdn.testnet |

# How It Works

## Buy USN for NEAR

_Method:_ `buy`

<img alt="Buy USN" src="images/buy.svg" />

## Sell USN for NEAR with `sell` API

_Method:_ `sell`

<img alt="Sell USN" src="images/sell.svg" />

## Slippage

Methods `buy` and `sell` requires the _expected_ exchange rate to avoid slippage. If the price suddenly changes (slips) out of the expected deviation the USN contract aborts the transaction.

# Build

First, install prerequisites:

```bash
npm install
```

Then, build.

For local sandbox:

```bash
npm run build
```

For testnet:

```bash
npm run build:testnet
```

For mainnet:

```bash
npm run build:mainnet
```

**WARNING**: There is a difference in each target. The crucial difference is that they communicate with different oracle addresses:

- Mainnet: `priceoracle.near`
- Testnet: `priceoracle.testnet`
- Sandbox: `priceoracle.test.near`

And all these oracle contracts report prices with different asset names.

# Test

## Run unit tests

```bash
cargo test
```

## Run integration tests

```bash
npm run build
npm run deploy
npm run test
```

## Manual testing on the Testnet

Build

```bash
npm run build:testnet
```

Deploy

```bash
near deploy --force --wasmFile target/wasm32-unknown-unknown/testnet/usn.wasm --accountId=usdn.testnet --masterAccount=usdn.testnet
```

Init once

```bash
near call usdn.testnet new --args '{"owner_id": "usdn.testnet"}' --accountId=usdn.testnet
```

Add a guardian

```bash
near call usdn.testnet extend_guardians --accountId usdn.testnet --args '{"guardians": ["alice.testnet"]}'
```

Buy and sell

```bash
# Send NEAR, buy USN.
near call usdn.testnet buy --accountId alice.testnet --amount 1 --gas 50000000000000

# Check USN balance.
near call usdn.testnet ft_balance_of --accountId alice.testnet --args '{"account_id": "alice.testnet"}'

# Sell USN, receive NEAR.
near call usdn.testnet sell --accountId alice.testnet --args '{"amount": "118800"}' --amount 0.000000000000000000000001 --gas 50000000000000

# Buy USN with slippage control
near call usdn.testnet buy --args '{"expected": {"multiplier": "111439", "slippage": "10", "decimals": "28" }}' --accountId alice.testnet --amount 1 --gas 50000000000000

# Buy USN and transfer to someone.
near call usdn.testnet buy --args '{"to": "bob.testnet"}' --accountId alice.testnet --amount 1 --gas 50000000000000
```

# DAO

## Upgrade the contract via Upgrade Proposal

1. Download `usn.mainnet.wasm` from https://github.com/binary-star-near/usn/releases
2. Create an upgrade proposal:
```bash
sputnikdao proposal upgrade usn.mainnet.wasm usn --daoAcc usn --accountId alice.near --network mainnet
```

# API

## Buy/sell USN

Send NEAR, receive USN.

```rust
pub fn buy(&mut self, expected: Option<ExpectedRate>, to: Option<AccountId>);
```

Send USN, receive NEAR.

```rust
pub fn sell(&mut self, amount: U128, expected: Option<ExpectedRate>) -> Promise;
```

## View methods

```rust
pub fn contract_status(&self) -> ContractStatus;
pub fn name(&self) -> String;
pub fn symbol(&self) -> String;
pub fn decimals(&self) -> u8;
pub fn spread(&self, amount: Option<U128>) -> U128;
pub fn version(&self) -> String;
pub fn blacklist_status(&self, account_id: &AccountId) -> BlackListStatus;
pub fn owner(&self);
```

## NEP-141 (ERC-20)

```rust
pub fn ft_transfer(&mut self, receiver_id: AccountId, amount: U128, memo: Option<String>);
pub fn ft_transfer_call(
&mut self,
receiver_id: AccountId,
amount: U128,
memo: Option<String>,
msg: String,
) -> PromiseOrValue<U128>;
pub fn ft_total_supply(&self) -> U128;
pub fn ft_balance_of(&self, account_id: AccountId) -> U128;
pub fn ft_metadata(&self) -> FungibleTokenMetadata;
```

## NEP-145: partial storage API

Always returns 125 milliNEAR indicating that user doesn't need to be registered
with `storage_deposit`.

```rust
pub fn storage_balance_of(&self, account_id: AccountId) -> Option<StorageBalance>;
```

## Constructor

```rust
pub fn new(owner_id: AccountId) -> Self;
```

## Private setters

For owner only.

```rust
pub fn upgrade_name_symbol(&mut self, name: String, symbol: String);
pub fn upgrade_icon(&mut self, data: String);
pub fn add_to_blacklist(&mut self, account_id: &AccountId);
pub fn remove_from_blacklist(&mut self, account_id: &AccountId);
pub fn destroy_black_funds(&mut self, account_id: &AccountId);
pub fn pause(&mut self);
pub fn resume(&mut self);
pub fn set_fixed_spread(&mut self, spread: U128) {
pub fn set_adaptive_spread(&mut self, params: Option<ExponentialSpreadParams>);
pub fn set_owner(&mut self, owner_id: AccountId);
pub fn extend_guardians(&mut self, guardians: Vec<AccountId>);
pub fn remove_guardians(&mut self, guardians: Vec<AccountId>);
```

## Upgradability

```rust
pub fn upgrade();
pub fn migrate() -> Self;
```
23 changes: 23 additions & 0 deletions images/buy.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
@startuml

title Buy USN

alice -> usn: send NEAR\n+ expected rate\n+ slippage\n+ transfer to

usn -> priceoracle: ""get_price_data""
activate priceoracle
usn <- priceoracle: NEAR/USDT rate
deactivate priceoracle
usn -> usn: verify timestamp

alt if expected rate and slippage is passed
usn -> usn: assert slippage
end

usn -> usn: mint USN

alice <-- usn: USN amount
alt If "transfer to" is defined
bob <-- usn: USN amount
end
@enduml
Loading

0 comments on commit 5b660dc

Please sign in to comment.