Skip to content

Commit

Permalink
add oracle example (#102)
Browse files Browse the repository at this point in the history
  • Loading branch information
laizy authored Nov 20, 2020
1 parent f65c40e commit 1d8e435
Show file tree
Hide file tree
Showing 7 changed files with 212 additions and 2 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ members = [
"examples/call-neovm",
"examples/invoke-native-test",
"examples/notify-test",
"examples/call_native"
"examples/call_native",
"examples/oracle"
]

[profile.release]
Expand Down
19 changes: 19 additions & 0 deletions examples/oracle/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "oracle"
version = "0.1.0"
authors = ["qiluge <[email protected]>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

ontio-std = {git = "https://github.com/ontio/ontology-wasm-cdt-rust"}


[lib]
crate-type = ["cdylib", "rlib"] #Compile as a dynamic link library


[features]
mock = ["ontio-std/mock"]
59 changes: 59 additions & 0 deletions examples/oracle/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#![cfg_attr(not(feature = "mock"), no_std)]
#![feature(proc_macro_hygiene)]
extern crate ontio_std as ostd;

use ostd::abi::{Sink, Source};
use ostd::prelude::*;
use ostd::runtime::{check_witness, input, ret};

use method::*;
use storage::*;

pub mod method;
pub mod storage;

#[no_mangle]
pub fn invoke() {
let input = input();
let mut source = Source::new(&input);
let action: &[u8] = source.read().unwrap();
let mut sink = Sink::new(12);
match action {
b"init" => {
let admin = source.read().unwrap();
sink.write(initialize(admin));
}
b"isPriceOracle" => {
sink.write(true);
}
b"putUnderlyingPrice" => {
let (key_list, price_list) = source.read().unwrap();
sink.write(put_underlying_price(key_list, price_list));
}
b"getUnderlyingPrice" => {
let key = source.read().unwrap();
sink.write(get_price(key));
}
b"setDecimal" => {
let decimal = source.read().unwrap();
assert!(check_witness(&get_admin()), "check witness failed");
sink.write(put_decimal(decimal));
}
b"getDecimal" => {
sink.write(get_decimal());
}
_ => {
let method = str::from_utf8(action).ok().unwrap();
panic!("not support method:{}", method)
}
}
ret(sink.bytes());
}

#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
32 changes: 32 additions & 0 deletions examples/oracle/src/method.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use ostd::abi::EventBuilder;
use ostd::prelude::*;
use ostd::runtime::check_witness;
use ostd::types::U128;

use crate::storage::*;

/**
* @notice Initialize the money market
* @param admin The address of the Oracle
*/
pub fn initialize(admin: &Address) -> bool {
assert!(check_witness(&admin), "check witness failed");
assert!(!is_init(), "already init");
put_admin(admin);
init();
true
}

pub fn put_underlying_price(key_list: Vec<&str>, price_list: Vec<U128>) -> bool {
assert!(check_witness(&get_admin()), "check witness failed");
assert_eq!(key_list.len(), price_list.len(), "invalid param");
let mut event_builder = EventBuilder::new();
event_builder = event_builder.string("PutUnderlyingPrice");
for (key, price) in key_list.into_iter().zip(price_list.into_iter()) {
put_price(key, price);
event_builder = event_builder.string(key);
event_builder = event_builder.number(price);
}
event_builder.notify();
true
}
53 changes: 53 additions & 0 deletions examples/oracle/src/storage.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use ostd::database;
use ostd::prelude::*;
use ostd::types::U128;

/**
* @notice Administrator for this contract
*/
const ADMIN_KEY: &str = "admin";

pub fn put_admin(admin: &Address) {
database::put(ADMIN_KEY, admin);
}

pub fn get_admin() -> Address {
database::get(ADMIN_KEY).unwrap()
}

const INIT: &str = "init";

pub fn init() {
database::put(INIT, true);
}

pub fn is_init() -> bool {
database::get(INIT).unwrap_or(false)
}

/**
* @notice Price data for this contract
*/
const PRICE: &str = "price";

pub fn put_price(key: &str, price: U128) {
database::put(PRICE.to_string() + key, price);
}

pub fn get_price(key: &str) -> U128 {
database::get(PRICE.to_string() + key).unwrap()
}

/**
* @notice Decimal for this contract
*/
const DECIMAL: &str = "decimal";

pub fn put_decimal(decimal: u8) -> bool {
database::put(DECIMAL, decimal);
true
}

pub fn get_decimal() -> u8 {
database::get(DECIMAL).unwrap()
}
46 changes: 46 additions & 0 deletions examples/oracle/tests/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
extern crate ontio_std as ostd;
extern crate oracle;

use ostd::types::U128;
use ostd::{mock::build_runtime, prelude::*};

use oracle::method;
use oracle::storage;

#[test]
fn test_oracle() {
let runtime = &build_runtime();
let admin = Address::repeat_byte(1);
runtime.witness(&[admin.clone()]);
method::initialize(&admin);
storage::put_decimal(9);
assert_eq!(9, storage::get_decimal());
method::put_underlying_price(
vec!["ONT", "BTC", "ETH", "DAI"],
vec![U128::new(100), U128::new(10000), U128::new(400), U128::new(1)],
);
assert_eq!(U128::new(100), storage::get_price("ONT"));
assert_eq!(U128::new(10000), storage::get_price("BTC"));
assert_eq!(U128::new(400), storage::get_price("ETH"));
assert_eq!(U128::new(1), storage::get_price("DAI"));
}

#[test]
#[should_panic]
fn test_init_twice() {
let runtime = &build_runtime();
let admin = Address::repeat_byte(1);
runtime.witness(&[admin.clone()]);
method::initialize(&admin);
method::initialize(&admin);
}

#[test]
fn test_set_decimal_twice() {
let runtime = &build_runtime();
let admin = Address::repeat_byte(1);
runtime.witness(&[admin.clone()]);
method::initialize(&admin);
storage::put_decimal(9);
storage::put_decimal(7);
}
2 changes: 1 addition & 1 deletion ontio-std/src/abi/event_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ impl VmValueBuilderCommon {
// compile-fails

/// ```compile_fail
/// #[deny(unused_must_use)]
/// #![deny(unused_must_use)]
/// {
/// EventBuilder::new().bool(true);
/// }
Expand Down

0 comments on commit 1d8e435

Please sign in to comment.