Definition: [
"autonomous agent",
{
"doc_url": "https://testnet.oswap.io/pool.json",
"init": "{
$bounceFees = 1e4;
$minLiquidity = 1e3;
$factory = params.factory;
$asset0 = params.asset0;
$asset1 = params.asset1;
$swapFee = params.swap_fee;
$swapNoFee = 1e11 - $swapFee;
$asset = var[$factory]['get_asset.' || this_address];
$supply = var['supply'];
$amount0 = trigger.output[[asset=$asset0]];
$amount1 = trigger.output[[asset=$asset1]];
$amount0NoFees = ($asset0 == 'base') ? $amount0 - $bounceFees : $amount0;
$amount1NoFees = ($asset1 == 'base') ? $amount1 - $bounceFees : $amount1;
$reserve0 = balance[$asset0] - $amount0;
$reserve1 = balance[$asset1] - $amount1;
if (trigger.data.to AND !is_valid_address(trigger.data.to)) bounce('invalid recipient address');
if (trigger.data.to_aa AND !is_aa(trigger.data.to_aa)) bounce('invalid aa address');
$to = trigger.data.to OTHERWISE trigger.initial_address;
$toAA = trigger.data.to_aa;
$deadline = trigger.data.deadline;
if ($deadline AND $deadline < timestamp) bounce('expired');
}",
"messages": {
"cases": [
{
"if": "{trigger.data.info}",
"messages": [
{
"app": "state",
"state": "{
response['factory'] = $factory;
response['asset0'] = $asset0;
response['asset1'] = $asset1;
response['swap_fee'] = $swapFee;
response['reserve0'] = $reserve0;
response['reserve1'] = $reserve1;
response['asset'] = $asset;
response['supply'] = $supply;
}"
}
]
},
{
"if": "{!$asset AND trigger.data.initialize AND trigger.address == $factory}",
"messages": [
{
"app": "asset",
"payload": {
"is_private": false,
"is_transferrable": true,
"auto_destroy": false,
"fixed_denominations": false,
"issued_by_definer_only": true,
"cosigned_by_definer": false,
"spender_attested": false
}
},
{
"app": "payment",
"payload": {
"asset": "base",
"outputs": [
{
"address": "{$factory}"
}
]
}
},
{
"app": "data",
"payload": {
"finalize": "1"
}
},
{
"app": "state",
"state": "{response['type'] = 'initialize';}"
}
]
},
{
"if": "{
$both = ($amount0NoFees > 0 AND $amount1NoFees > 0);
$asset0Only = ($amount0NoFees > 0 AND $amount1NoFees <= 0);
$asset1Only = ($amount1NoFees > 0 AND $amount0NoFees <= 0);
$asset AND ($both OR trigger.data.mint AND ($asset0Only OR $asset1Only))
}",
"init": "{
if (
($both AND ($amount0NoFees * $amount1NoFees) < $minLiquidity)
OR (($asset0Only OR $asset1Only) AND ($amount0NoFees + $amount1NoFees) < $minLiquidity)
)
bounce('not enough liquidity, minimum is ' || $minLiquidity);
if ($reserve1 == 0 OR $reserve0 == 0) {
if (!$both) bounce('initial contribution must have both tokens');
$minted = balance[$asset0];
return;
}
if ($both) {
$ratio = $reserve1 / $reserve0;
$expectedAmount1 = round($ratio * $amount0);
if ($expectedAmount1 != $amount1 OR $expectedAmount1 == 0)
bounce('wrong ratio of amounts, expected ' || $expectedAmount1 || ' of ' || $asset1);
$share = $amount0 / $reserve0;
} else if ($asset0Only) {
$share = (sqrt(1 + $amount0 / $reserve0) - 1) / 1e11 * $swapNoFee;
} else if ($asset1Only) {
$share = (sqrt(1 + $amount1 / $reserve1) - 1) / 1e11 * $swapNoFee;
}
$minted = floor($share * $supply);
if ($minted == 0) bounce('insufficient minted amount');
}",
"messages": [
{
"app": "payment",
"payload": {
"asset": "{$asset}",
"outputs": [
{
"address": "{$to}",
"amount": "{$minted}"
}
]
}
},
{
"app": "state",
"state": "{
var['supply'] += $minted;
response['type'] = 'mint';
response['asset_amount'] = $minted;
}"
}
]
},
{
"if": "{$asset AND trigger.output[[asset=$asset]]}",
"init": "{
$burned = trigger.output[[asset=$asset]];
$share = $burned / $supply;
$minted0 = floor($share * $reserve0);
$minted1 = floor($share * $reserve1);
if ($minted0 == 0 OR $minted1 == 0) bounce('insufficient output amount');
}",
"messages": [
{
"app": "payment",
"payload": {
"asset": "{$asset0}",
"outputs": [
{
"address": "{$to}",
"amount": "{$minted0}"
}
]
}
},
{
"app": "payment",
"payload": {
"asset": "{$asset1}",
"outputs": [
{
"address": "{$to}",
"amount": "{$minted1}"
}
]
}
},
{
"app": "state",
"state": "{
var['supply'] -= $burned;
response['type'] = 'burn';
response['asset0_amount'] = $minted0;
response['asset1_amount'] = $minted1;
}"
}
]
},
{
"if": "{
$asset0ToAsset1 = ($amount0NoFees > 0 AND $amount1NoFees <= 0);
$asset1ToAsset0 = ($amount1NoFees > 0 AND $amount0NoFees <= 0);
$asset AND $supply AND ($asset0ToAsset1 OR $asset1ToAsset0)
}",
"init": "{
$amountOutMin = trigger.data.amount_out_min;
$in = $asset0ToAsset1 ? '0' : '1';
$out = $asset0ToAsset1 ? '1' : '0';
$numerator = ${'amount' || $in} * ${'reserve' || $out} * $swapNoFee;
$denominator = ${'reserve' || $in} * 1e11 + ${'amount' || $in} * $swapNoFee;
$amount = floor($numerator / $denominator);
if ($amount == 0 OR ($amountOutMin AND $amount < $amountOutMin))
bounce('insufficient output amount');
$address = $toAA ? $toAA : $to;
}",
"messages": [
{
"app": "payment",
"payload": {
"asset": "{${'asset' || $out}}",
"outputs": [
{
"address": "{$address}",
"amount": "{$amount}"
}
]
}
},
{
"if": "{$toAA}",
"app": "data",
"payload": {
"to": "{$to}"
}
},
{
"app": "state",
"state": "{
response['type'] = 'swap';
response['asset' || $out || '_amount'] = $amount;
}"
}
]
}
]
}
}
]