Exchange Rate

state.rs

Stores all relevant contract parameters.
1
pub struct Config {
2
pub owner: HumanAddr,
3
}
4
Copied!
owner: the owner address of this contract.
1
pub struct Token {
2
pub status: Status,
3
pub exchange_rate: Decimal256,
4
pub epoch_period: u64,
5
pub weight: Decimal256,
6
pub last_updated_at: u64,
7
}
8
Copied!
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.
1
pub fn init<S: Storage, A: Api, Q: Querier>(
2
deps: &mut Extern<S, A, Q>,
3
env: Env,
4
_: InitMsg,
5
) -> StdResult<InitResponse> {
6
state::store_config(
7
&mut deps.storage,
8
&state::Config {
9
owner: env.message.sender,
10
},
11
)?;
12
13
Ok(InitResponse::default())
14
}
15
Copied!
Initializes a new Exchange Rate contract.
1
pub fn handle<S: Storage, A: Api, Q: Querier>(
2
deps: &mut Extern<S, A, Q>,
3
env: Env,
4
msg: HandleMsg,
5
) -> StdResult<HandleResponse> {
6
match msg {
7
HandleMsg::Update { token } => Ok(ExecHandler::update(deps, env, token)?),
8
HandleMsg::ConfigToken {
9
token,
10
exchange_rate,
11
epoch_period,
12
weight,
13
} => Ok(ExecHandler::config_token(
14
deps,
15
env,
16
token,
17
exchange_rate,
18
epoch_period,
19
weight,
20
)?),
21
HandleMsg::AddToken {
22
token,
23
base_rate,
24
period,
25
weight,
26
} => Ok(ExecHandler::add_token(
27
deps, env, token, base_rate, period, weight,
28
)?),
29
HandleMsg::Start { tokens } => Ok(ExecHandler::start(deps, env, tokens)?),
30
HandleMsg::Stop { tokens } => Ok(ExecHandler::stop(deps, env, tokens)?),
31
}
32
}
33
Copied!
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.
1
pub fn query<S: Storage, A: Api, Q: Querier>(
2
deps: &Extern<S, A, Q>,
3
msg: QueryMsg,
4
) -> StdResult<Binary> {
5
match msg {
6
QueryMsg::ExchangeRateOf { token, blocktime } => {
7
Ok(QueryHandler::exchange_rate_of(deps, &token, blocktime)?)
8
}
9
}
10
}
11
Copied!
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.
1
pub fn update<S: Storage, A: Api, Q: Querier>(
2
deps: &mut Extern<S, A, Q>,
3
env: Env,
4
token: HumanAddr,
5
) -> StdResult<HandleResponse> {
6
let token_addr: CanonicalAddr = deps.api.canonical_address(&token)?;
7
8
let mut token: state::Token = state::read_token(&deps.storage, &token_addr)?;
9
if token.status.ne(&state::Status::Running) {
10
return Err(StdError::unauthorized());
11
}
12
13
let elapsed = env.block.time.sub(token.last_updated_at);
14
if elapsed < token.epoch_period {
15
return Ok(HandleResponse::default());
16
}
17
18
let exchange_rate_before = token.exchange_rate;
19
let pow_count = elapsed.div(token.epoch_period);
20
for _ in 0..pow_count {
21
token.exchange_rate = token.exchange_rate.mul(token.weight);
22
}
23
24
token.last_updated_at = env.block.time;
25
26
state::store_token(&mut deps.storage, &token_addr, &token)?;
27
28
Ok(HandleResponse {
29
messages: vec![],
30
log: vec![
31
log("action", "update"),
32
log("sender", env.message.sender),
33
log("er_before", exchange_rate_before),
34
log("er_after", token.exchange_rate),
35
],
36
data: None,
37
})
38
}
39
Copied!
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
1
pub fn config_token<S: Storage, A: Api, Q: Querier>(
2
deps: &mut Extern<S, A, Q>,
3
env: Env,
4
token: HumanAddr,
5
exchange_rate: Option<Decimal256>,
6
epoch_period: Option<u64>,
7
weight: Option<Decimal256>,
8
) -> StdResult<HandleResponse> {
9
check_owner(deps, &env.message.sender)?;
10
11
let token_addr: CanonicalAddr = deps.api.canonical_address(&token)?;
12
let mut token: state::Token = state::read_token(&deps.storage, &token_addr)?;
13
14
if let Some(er) = exchange_rate {
15
if token.exchange_rate.gt(&er) {
16
return Err(StdError::unauthorized());
17
}
18
token.exchange_rate = er;
19
}
20
if let Some(ep) = epoch_period {
21
token.epoch_period = ep;
22
}
23
if let Some(w) = weight {
24
token.weight = w;
25
}
26
27
state::store_token(&mut deps.storage, &token_addr, &token)?;
28
29
Ok(HandleResponse::default())
30
}
31
Copied!
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.
1
pub fn add_token<S: Storage, A: Api, Q: Querier>(
2
deps: &mut Extern<S, A, Q>,
3
env: Env,
4
token: HumanAddr,
5
base_rate: Decimal256,
6
period: u64,
7
weight: Decimal256,
8
) -> StdResult<HandleResponse> {
9
check_owner(deps, &env.message.sender)?;
10
11
let token_addr: CanonicalAddr = deps.api.canonical_address(&token)?;
12
13
state::store_token(
14
&mut deps.storage,
15
&token_addr,
16
&state::Token {
17
exchange_rate: base_rate,
18
epoch_period: period,
19
status: state::Status::Neutral,
20
weight,
21
last_updated_at: env.block.time,
22
},
23
)?;
24
25
Ok(HandleResponse::default())
26
}
Copied!
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.
1
pub fn start<S: Storage, A: Api, Q: Querier>(
2
deps: &mut Extern<S, A, Q>,
3
env: Env,
4
tokens: Vec<HumanAddr>,
5
) -> StdResult<HandleResponse> {
6
check_owner(deps, &env.message.sender)?;
7
for token in tokens {
8
_start(deps, &token, &env.block.time)?;
9
}
10
Ok(HandleResponse::default())
11
}
12
13
fn _start<S: Storage, A: Api, Q: Querier>(
14
deps: &mut Extern<S, A, Q>,
15
token: &HumanAddr,
16
block_time: &u64,
17
) -> StdResult<()> {
18
let token_addr: CanonicalAddr = deps.api.canonical_address(&token)?;
19
let mut token: state::Token = state::read_token(&deps.storage, &token_addr)?;
20
21
token.status = state::Status::Running;
22
token.last_updated_at = *block_time;
23
24
Ok(())
25
}
26
Copied!
Changes token.status to Running for all tokens registered with the Exchange Rate contract.
1
pub fn stop<S: Storage, A: Api, Q: Querier>(
2
deps: &mut Extern<S, A, Q>,
3
env: Env,
4
tokens: Vec<HumanAddr>,
5
) -> StdResult<HandleResponse> {
6
check_owner(deps, &env.message.sender)?;
7
for token in tokens {
8
_stop(deps, token)?;
9
}
10
11
Ok(HandleResponse {
12
messages: vec![],
13
log: vec![log("action", "stop"), log("sender", env.message.sender)],
14
data: None,
15
})
16
}
17
18
fn _stop<S: Storage, A: Api, Q: Querier>(
19
deps: &mut Extern<S, A, Q>,
20
token: HumanAddr,
21
) -> StdResult<()> {
22
let token_addr: CanonicalAddr = deps.api.canonical_address(&token)?;
23
let mut token: state::Token = state::read_token(&deps.storage, &token_addr)?;
24
25
token.status = state::Status::Stopped;
26
27
Ok(())
28
}
29
Copied!
Changes token.status to Stopped for all tokens registered with the Exchange Rate contract.
Last modified 3mo ago