Definition: [
"autonomous agent",
{
"doc_url": "https://ostable.org/bonded-stablecoin-governance.json",
"init": "{
$regular_challenging_period = params.regular_challenging_period OTHERWISE 3*24*3600;
$important_challenging_period = params.important_challenging_period OTHERWISE 30*24*3600;
// one cannot withdraw for this period after voting for a winning value
$freeze_period = params.freeze_period OTHERWISE 30*24*3600;
// min share of token1 supply required to approve a proposal
$proposal_min_support = params.proposal_min_support OTHERWISE 0.5;
$curve_aa = params.curve_aa;
if (!$curve_aa)
bounce("no curve_aa");
$fund_aa = var[$curve_aa]['fund_aa'];
$asset = var[$fund_aa]['shares_asset'];
$names = ['fee_multiplier', 'moved_capacity_share', 'threshold_distance', 'move_capacity_timeout', 'slow_capacity_share', 'interest_rate', 'oracles', 'proposal', 'deposits.min_deposit_term', 'deposits.challenging_period', 'deposits.challenge_immunity_period', 'deposits.reporter_share', 'decision_engine_aa'];
$is_allowed_name = $name => {
length(filter($names, 20, $n => $n == $name)) == 1
};
$get_challenging_period = ($name) => ($name == 'oracles' OR $name == 'decision_engine_aa') ? $important_challenging_period : $regular_challenging_period;
$get_oracles = $oracles_string => {
$pairs = split($oracles_string, " ");
if (length($pairs) > 3)
bounce("too many oracles");
$oracles_data = map($pairs, 3, $pair => {
$oracle = substring($pair, 0, 32);
if (!is_valid_address($oracle))
bounce("invalid oracle address: " || $oracle);
$op = substring($pair, 32, 1);
if ($op != '*' AND $op != '/')
bounce("invalid format of oracles, should be oracle*feed_name or oracle/feed_name");
$feed_name = substring($pair, 33);
{
oracle: $oracle,
feed_name: $feed_name,
op: $op,
}
});
$oracles_data
};
$get_value_key = $value => {
$key_len = length('support_' || 'oracles' || '_' || $value || '_') + 32;
($key_len > 128) ? sha256($value) : $value
};
}",
"messages": {
"cases": [
{
"if": "{ trigger.data.name AND trigger.data.commit }",
"init": "{
$name = trigger.data.name;
$leader = var['leader_' || $name];
$current_value = var[$name];
if (!exists($leader)) // can be 0
bounce("no leader");
if (exists($current_value) AND $leader == $current_value)
bounce("already equal to leader");
if (var['challenging_period_start_ts_' || $name] + $get_challenging_period($name) > timestamp)
bounce("challenging period not expired yet");
if ($name == 'proposal'){
$expiry = var['proposal_' || $leader || '_expiry'];
if (parse_date($expiry) < timestamp)
bounce("the proposal has expired");
if (var['proposal_' || $leader || '_approved'])
bounce("the proposal has already been approved");
$support = var['support_' || $name || '_' || $leader];
if ($support < var[$fund_aa]['shares_supply'] * $proposal_min_support)
bounce("not enough support for the proposal");
$proposal_amount = var['proposal_' || $leader || '_amount'];
if ($proposal_amount == 0) // it cannot be committed and will never become approved
bounce("the proposal is 0 amount");
}
}",
"messages": [
{
"app": "payment",
"payload": {
"asset": "base",
"outputs": [
{
"address": "{$name == 'proposal' ? var[$curve_aa]['decision_engine_aa'] : $curve_aa}",
"amount": 5000
}
]
}
},
{
"if": "{$name != 'proposal'}",
"app": "data",
"payload": {
"name": "{$name}",
"value": "{($name == 'oracles') ? $get_oracles($leader) : $leader}"
}
},
{
"if": "{$name == 'proposal'}",
"app": "data",
"payload": {
"grant": 1,
"recipient": "{var['proposal_' || $leader || '_recipient']}",
"amount": "{var['proposal_' || $leader || '_amount']}"
}
},
{
"app": "state",
"state": "{
if ($name != 'proposal')
var[$name] = $leader;
else
var['proposal_' || $leader || '_approved'] = 1;
}"
}
]
},
{
"if": "{ trigger.data.name }",
"init": "{
$balance = var['balance_' || trigger.address] + trigger.output[[asset=$asset]];
if (!$balance)
bounce("you have no deposited balance and cannot vote");
$name = trigger.data.name;
$value = trigger.data.value; // can be empty to remove one's vote
if (!$is_allowed_name($name))
bounce("unknown name: " || $name);
if (exists($value)){
if ($name == 'fee_multiplier' AND !(typeof($value) == 'number' AND $value >= 0))
bounce("invalid value");
if ($name == 'moved_capacity_share' AND !(typeof($value) == 'number' AND $value > 0 AND $value <= 1))
bounce("invalid value");
if ($name == 'threshold_distance' AND !(typeof($value) == 'number' AND $value > 0 AND $value <= 0.2))
bounce("invalid value");
if ($name == 'move_capacity_timeout' AND !(is_integer($value) AND $value > 0))
bounce("invalid value");
if ($name == 'slow_capacity_share' AND !(typeof($value) == 'number' AND $value >= 0 AND $value <= 1))
bounce("invalid value");
if ($name == 'interest_rate' AND !(typeof($value) == 'number' AND $value >= 0))
bounce("invalid value");
if ($name == 'oracles')
$oracles_data = $get_oracles($value); // will bounce if the format is bad
if ($name == 'deposits.min_deposit_term' AND !(is_integer($value) AND $value >= 0))
bounce("invalid value");
if ($name == 'deposits.challenging_period' AND !(is_integer($value) AND $value >= 0))
bounce("invalid value");
if ($name == 'deposits.challenge_immunity_period' AND !(is_integer($value) AND $value >= 0))
bounce("invalid value");
if ($name == 'deposits.reporter_share' AND !(typeof($value) == 'number' AND $value >= 0 AND $value <= 1))
bounce("invalid value");
if ($name == 'decision_engine_aa' AND !is_aa($value))
bounce("invalid value");
if ($name == 'proposal'){
if (!(is_integer($value) AND $value > 0))
bounce("invalid value");
$expiry = var['proposal_' || $value || '_expiry'];
if (!$expiry)
bounce("no such proposal");
if (parse_date($expiry) < timestamp)
bounce("the proposal has expired");
if (var['proposal_' || $value || '_approved'])
bounce("the proposal has already been approved");
}
}
}",
"messages": [
{
"app": "state",
"state": "{
if (trigger.output[[asset=$asset]])
var['balance_' || trigger.address] += trigger.output[[asset=$asset]];
$prev_choice = var['choice_' || trigger.address || '_' || $name];
$leader = var['leader_' || $name];
if (exists($leader) AND exists($prev_choice) AND $prev_choice == $leader AND var['challenging_period_start_ts_' || $name] + $get_challenging_period($name) + $freeze_period > timestamp)
bounce("you cannot change your vote yet");
var['choice_' || trigger.address || '_' || $name] = $value;
if (exists($prev_choice)){
$prev_choice_key = $get_value_key($prev_choice);
var['support_' || $name || '_' || $prev_choice_key] -= var['support_' || $name || '_' || $prev_choice_key || '_' || trigger.address];
var['support_' || $name || '_' || $prev_choice_key || '_' || trigger.address] = false;
}
if (exists($value)){
$value_key = $get_value_key($value);
var['support_' || $name || '_' || $value_key] += $balance;
var['support_' || $name || '_' || $value_key || '_' || trigger.address] = $balance;
if (!exists($leader) OR var['support_' || $name || '_' || $value_key] > var['support_' || $name || '_' || $get_value_key($leader)]){
var['leader_' || $name] = $value;
var['challenging_period_start_ts_' || $name] = timestamp;
}
}
}"
}
]
},
{
"if": "{ trigger.data.withdraw }",
"init": "{
$balance = var['balance_' || trigger.address] + trigger.output[[asset=$asset]];
if (!$balance)
bounce("you have no deposited balance and cannot withdraw");
$amount = trigger.data.amount OTHERWISE $balance;
if ($amount > $balance)
bounce("your balance is only " || $balance);
foreach($names, 13, $name => {
if (var['choice_' || trigger.address || '_' || $name])
bounce("support for " || $name || " not removed yet");
});
}",
"messages": [
{
"app": "payment",
"payload": {
"asset": "{$asset}",
"outputs": [
{
"address": "{trigger.address}",
"amount": "{ $amount }"
}
]
}
},
{
"app": "state",
"state": "{
var['balance_' || trigger.address] -= $amount;
}"
}
]
},
{
"if": "{ trigger.data.add_proposal AND trigger.data.type AND definition[$curve_aa][1].params.allow_grants }",
"init": "{
if (trigger.data.type != 'grant')
bounce("unrecognized proposal type");
if (!is_valid_address(trigger.data.recipient))
bounce("invalid grant recipient address");
if (!is_integer(trigger.data.amount) OR trigger.data.amount < 0)
bounce("invalid grant amount");
if (!unit[trigger.data.unit])
bounce("proposal unit not found");
if (!trigger.data.expiry)
bounce("proposal expiry date not set");
$expiry_ts = parse_date(trigger.data.expiry);
if (!$expiry_ts)
bounce("invalid expiry date");
}",
"messages": [
{
"app": "state",
"state": "{
var['count_proposals'] += 1;
$num = var['count_proposals'];
var['proposal_' || $num || '_recipient'] = trigger.data.recipient;
var['proposal_' || $num || '_amount'] = trigger.data.amount;
var['proposal_' || $num || '_unit'] = trigger.data.unit;
var['proposal_' || $num || '_expiry'] = trigger.data.expiry;
}"
}
]
}
]
}
}
]