Deployed at: terra1zvsv534gx7xppq4yfstslmsgc3jmkfak4mlrv4
state.rs
Stores all relevant contract parameters.
Copy pub struct Config {
pub owner : HumanAddr ,
}
owner
: the owner address of this contract.
Copy pub struct Token {
pub status : Status ,
pub exchange_rate : Decimal256 ,
pub epoch_period : u64 ,
pub weight : Decimal256 ,
pub last_updated_at : u64 ,
}
status
: virtual exchange rate enforcement status - Neutral
, Running
, or Stopped
Neutral
: logic not yet initialized, throws an error when queried
Running
: exchange rate calculations valid, returns current exchange_rate
when queried & executes update
Stopped
: exchange rate no longer updating, returns a constant value when queried
exchange_rate
: current virtual exchange rate for this pool
epoch_period
: minimum time gap between update()
calls.
contract.rs
Defines logic entry points for InitMsg
, HandleMsg
and QueryMsg
calls.
Copy pub fn init < S : Storage , A : Api , Q : Querier >(
deps : &mut Extern < S , A , Q >,
env : Env ,
_ : InitMsg ,
) -> StdResult < InitResponse > {
state :: store_config (
&mut deps . storage,
& state :: Config {
owner : env . message . sender,
},
) ? ;
Ok ( InitResponse :: default ())
}
Initializes a new Exchange Rate contract.
Copy pub fn handle < S : Storage , A : Api , Q : Querier >(
deps : &mut Extern < S , A , Q >,
env : Env ,
msg : HandleMsg ,
) -> StdResult < HandleResponse > {
match msg {
HandleMsg :: Update { token } => Ok ( ExecHandler :: update (deps, env, token) ? ),
HandleMsg :: ConfigToken {
token,
exchange_rate,
epoch_period,
weight,
} => Ok ( ExecHandler :: config_token (
deps,
env,
token,
exchange_rate,
epoch_period,
weight,
) ? ),
HandleMsg :: AddToken {
token,
base_rate,
period,
weight,
} => Ok ( ExecHandler :: add_token (
deps, env, token, base_rate, period, weight,
) ? ),
HandleMsg :: Start { tokens } => Ok ( ExecHandler :: start (deps, env, tokens) ? ),
HandleMsg :: Stop { tokens } => Ok ( ExecHandler :: stop (deps, env, tokens) ? ),
}
}
Defines HandleMsg
endpoints. Calls the following functions per HandleMsg
:
Update { token }
: calls update(deps, env, token)
defined under handler_exec.rs
.
ConfigToken { token, exchange_rate, epoch_period, weight, }
: calls config_token(deps, env, token, exchange_rate, epoch_period, weight, )
defined under handler_exec.rs
.
AddToken { token, base_rate, period, weight, }
: calls add_token(deps, env, token, base_rate, period, weight, )
defined under handler_exec.rs
.
Start { tokens }
: calls start(deps, env, tokens)
defined under handler_exec.rs
.
Stop { tokens }
: calls stop(deps, env, tokens)
defined under handler_exec.rs
.
Copy pub fn query < S : Storage , A : Api , Q : Querier >(
deps : & Extern < S , A , Q >,
msg : QueryMsg ,
) -> StdResult < Binary > {
match msg {
QueryMsg :: ExchangeRateOf { token, blocktime } => {
Ok ( QueryHandler :: exchange_rate_of (deps, & token, blocktime) ? )
}
}
}
Defines QueryMsg
endpoints. Calls the following functions per QueryMsg
:
ExchangeRateOf { token, blocktime }
: calls exchange_rate_of(deps, &token, blocktime)
defined under handler_query.rs
; Queries the current exchange_rate
for token
.
handler_exec.rs
Defines core contract execution logic. Functions are as follows:
update
: recalculates the current virtual exchange rate for token
.
config_token
: updates target token
profile for calculating virtual exchange rate.
add_token
: adds a new target token
profile for calculating virtual exchange rate.
start
: enables virtual exchange rate calculation.
stop
: disables virtual exchange rate calculation.
Copy pub fn update < S : Storage , A : Api , Q : Querier >(
deps : &mut Extern < S , A , Q >,
env : Env ,
token : HumanAddr ,
) -> StdResult < HandleResponse > {
let token_addr : CanonicalAddr = deps . api . canonical_address ( & token) ? ;
let mut token : state :: Token = state :: read_token ( & deps . storage, & token_addr) ? ;
if token . status . ne ( & state :: Status :: Running ) {
return Err ( StdError :: unauthorized ());
}
let elapsed = env . block . time . sub (token . last_updated_at);
if elapsed < token . epoch_period {
return Ok ( HandleResponse :: default ());
}
let exchange_rate_before = token . exchange_rate;
let pow_count = elapsed . div (token . epoch_period);
for _ in 0 .. pow_count {
token . exchange_rate = token . exchange_rate . mul (token . weight);
}
token . last_updated_at = env . block . time;
state :: store_token ( &mut deps . storage, & token_addr, & token) ? ;
Ok ( HandleResponse {
messages : vec! [],
log : vec! [
log ( "action" , "update" ),
log ( "sender" , env . message . sender),
log ( "er_before" , exchange_rate_before),
log ( "er_after" , token . exchange_rate),
],
data : None ,
})
}
Recalculates virtual exchange rate for a particular token
.
exchange_rate
is calculated as:
count how many epochs have elapsed since last_updated_at
do nothing if at least one epoch has not passed
exchange_rate = exchange_rate * weight ^ epochs_passed
Copy pub fn config_token < S : Storage , A : Api , Q : Querier >(
deps : &mut Extern < S , A , Q >,
env : Env ,
token : HumanAddr ,
exchange_rate : Option < Decimal256 >,
epoch_period : Option < u64 >,
weight : Option < Decimal256 >,
) -> StdResult < HandleResponse > {
check_owner (deps, & env . message . sender) ? ;
let token_addr : CanonicalAddr = deps . api . canonical_address ( & token) ? ;
let mut token : state :: Token = state :: read_token ( & deps . storage, & token_addr) ? ;
if let Some (er) = exchange_rate {
if token . exchange_rate . gt ( & er) {
return Err ( StdError :: unauthorized ());
}
token . exchange_rate = er;
}
if let Some (ep) = epoch_period {
token . epoch_period = ep;
}
if let Some (w) = weight {
token . weight = w;
}
state :: store_token ( &mut deps . storage, & token_addr, & token) ? ;
Ok ( HandleResponse :: default ())
}
Updates virtual exchange rate parameters for token
. Accepts:
token
: address of the target token subject to exchange rate updates.
exchange_rate
: initial exchange rate parameter to be used as a baseline. should be reset on significant deviation.
epoch_period
: time length of a single epoch used for update
calls.
weight
: exchange rate delta enforced per epoch
.
Copy pub fn add_token < S : Storage , A : Api , Q : Querier >(
deps : &mut Extern < S , A , Q >,
env : Env ,
token : HumanAddr ,
base_rate : Decimal256 ,
period : u64 ,
weight : Decimal256 ,
) -> StdResult < HandleResponse > {
check_owner (deps, & env . message . sender) ? ;
let token_addr : CanonicalAddr = deps . api . canonical_address ( & token) ? ;
state :: store_token (
&mut deps . storage,
& token_addr,
& state :: Token {
exchange_rate : base_rate,
epoch_period : period,
status : state :: Status :: Neutral ,
weight,
last_updated_at : env . block . time,
},
) ? ;
Ok ( HandleResponse :: default ())
}
Adds a new token
target profile for calculating exchange_rate
. Accepts:
token
: address of the target token subject to exchange rate updates.
exchange_rate
: initial exchange rate parameter to be used as a baseline. should be reset on significant deviation.
epoch_period
: time length of a single epoch used for update
calls.
weight
: exchange rate delta enforced per epoch
.
Copy pub fn start < S : Storage , A : Api , Q : Querier >(
deps : &mut Extern < S , A , Q >,
env : Env ,
tokens : Vec < HumanAddr >,
) -> StdResult < HandleResponse > {
check_owner (deps, & env . message . sender) ? ;
for token in tokens {
_start (deps, & token, & env . block . time) ? ;
}
Ok ( HandleResponse :: default ())
}
fn _start < S : Storage , A : Api , Q : Querier >(
deps : &mut Extern < S , A , Q >,
token : & HumanAddr ,
block_time : & u64 ,
) -> StdResult <()> {
let token_addr : CanonicalAddr = deps . api . canonical_address ( & token) ? ;
let mut token : state :: Token = state :: read_token ( & deps . storage, & token_addr) ? ;
token . status = state :: Status :: Running ;
token . last_updated_at = * block_time;
Ok (())
}
Changes token.status
to Running
for all tokens registered with the Exchange Rate contract.
Copy pub fn stop < S : Storage , A : Api , Q : Querier >(
deps : &mut Extern < S , A , Q >,
env : Env ,
tokens : Vec < HumanAddr >,
) -> StdResult < HandleResponse > {
check_owner (deps, & env . message . sender) ? ;
for token in tokens {
_stop (deps, token) ? ;
}
Ok ( HandleResponse {
messages : vec! [],
log : vec! [ log ( "action" , "stop" ), log ( "sender" , env . message . sender)],
data : None ,
})
}
fn _stop < S : Storage , A : Api , Q : Querier >(
deps : &mut Extern < S , A , Q >,
token : HumanAddr ,
) -> StdResult <()> {
let token_addr : CanonicalAddr = deps . api . canonical_address ( & token) ? ;
let mut token : state :: Token = state :: read_token ( & deps . storage, & token_addr) ? ;
token . status = state :: Status :: Stopped ;
Ok (())
}
Changes token.status
to Stopped
for all tokens registered with the Exchange Rate contract.