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.