sidebar_position |
---|
1 |
import Admonition from '@theme/Admonition'
The Generator
contract allocates token rewards (ASTRO) for various LP tokens and distributes them pro-rata to LP stakers. In order to update allocation points (and the distribution of ASTRO emissions), an on-chain proposal must be submitted.
The proposal takes in an executable_message
that points to the setup_pools
endpoint within the Generator
contract. The setup_pools
endpoint creates a new list of pools
with allocation points and updates the contract’s config.
Use when submitting a proposal to adjust allocation points through the Astroport Web App. This tutorial walks you through the Executable Messages
field of the proposal.
<CH.Section> <CH.Scrollycoding>
### `Vec<ProposalMessage>`
The Executable Messages field in our proposal takes in a vector containing objects of type [`ProposalMessage`](../../develop/smart-contracts/astral-assembly#proposalmessage). Each `ProposalMessage` requires the following parameters:
- `order`: The order of execution of the message
- `msg`: Execution message of type [`CosmosMsg`](https://docs.rs/cosmwasm-std/latest/cosmwasm_std/enum.CosmosMsg.html)
```json
[
{
{
"wasm": {
"execute": {
"contract_addr": generatorAddress,
"msg": toBase64(
{
"setup_pools": {
"pools" : [
[
"terra18mcmlf4v23ehukkh7qxgpf5tznzg6893fxmf9ffmdt9phgf365zqvmlug6",
"1538"
],
[
"terra16esjk7qqlgh8w7p2a58yxhgkfk4ykv72p7ha056zul58adzjm6msvc674t",
"30018"
],
etc...
]
}
}
),
"funds": []
}
}
}
}
]
```
---
#### `wasm`
`CosmosMsg` is an enum that supports various types of messages. To adjust allocation points, our `CosmosMsg` must be of type [`wasm`](https://docs.rs/cosmwasm-std/latest/cosmwasm_std/enum.WasmMsg.html). Furthermore, our `wasm` message must be of type [`execute`](https://docs.rs/cosmwasm-std/latest/cosmwasm_std/enum.WasmMsg.html#variant.Execute). In the backgrund, we are creating a wasm contract call to the [`setup_pools`](../../develop/smart-contracts/tokenomics/generator#setup_pools) endpoint in the [`Generator`](../../develop/smart-contracts/tokenomics/generator) contract.
```json focus=4:27
```
#### `execute`
The `execute` operation requires the following parameters:
- `contract_addr`: Address of the contract where the execute message is being sent to. For adjusting allocation points, this would be the [`Generator`](../../develop/smart-contracts/tokenomics/generator) contract.
- `msg`: A binary encoded message containing our contract call.
- `funds`: Any funds to send along with our transaction.
<Admonition type="info" title="NOTE">
This tutorial uses placeholder variables for contract addresses. Use the actual string representation of each contract address when submitting a proposal.
</Admonition>
---
#### `msg`
The code in this section uses a custom function (`toBase64`) to display our binary message - this function needs to be defined elsewhere to be used and is **not accessible** within the Astroport Web App.
**Use for demonstration purposes only.** The actual string representation of our message will be an encoded binary, which will be covered below.
```json focus=7:23
```
---
### `setup_pools`
To adjust ASTRO allocation points a pool, our proposal `msg` must point to the [`setup_pools`](../../develop/smart-contracts/tokenomics/generator#setup_pools) endpoint in the [Generator](../../develop/smart-contracts/tokenomics/generator) contract.
`setup_pools` takes in `pools` - a vector that contains LP token addresses and allocation points. Two common mistakes:
- The message expects LP token addresses, not pair addresses.
- The message expects a vector of LP contract addresses. Specifying a single address rewrites all active pools with the pools specified in the message. You can query the generator contract to include previous LP token addresses and allocation points.
```json
{
"setup_pools": {
"pools" : [
[
"terra18mcmlf4v23ehukkh7qxgpf5tznzg6893fxmf9ffmdt9phgf365zqvmlug6",
"1538"
],
[
"terra16esjk7qqlgh8w7p2a58yxhgkfk4ykv72p7ha056zul58adzjm6msvc674t",
"30018"
],
[
"terra1ckmsqdhlky9jxcmtyj64crgzjxad9pvsd58k8zsxsnv4vzvwdt7qke04hl",
"40026"
],
[
"terra1kggfd6z0ad2k9q8v24f7ftxyqush8fp9xku9nyrjcs2wv0e4kypszfrfd0",
"6666"
],
[
"terra1cq22eugxwgp0x34cqfrxmd9jkyy43gas93yqjhmwrm7j0h5ecrqq5j7dgp",
"6666"
],
[
"terra1khsxwfnzuxqcyza2sraxf2ngkr3dwy9f7rm0uts0xpkeshs96ccsqtu6nv",
"11257"
],
[
"terra1h3z2zv6aw94fx5263dy6tgz6699kxmewlx3vrcu4jjrudg6xmtyqk6vt0u",
"6666"
],
[
"terra1ces6k6jp7qzkjpwsl6xg4f7zfwre0u23cglg69hhj3g20fhygtpsu24dsy",
"2152"
]
]
}
}
```
---
### Encoding our `setup_pools` `msg`
Our `setup_pools` message needs to be encoded and and passed as an input into our msg parameter within our execute call.
Since we are using the Astroport Web App to submit our proposal, we will encode our message manually using an [online Base64 encoder](https://www.base64encode.org/).
```json
```
---
#### Final Result
Once we encode our message, our final Executable Message that we would submit to the Astroport Web App to adjust allocation points ends up looking something like the code in this section.
You can see our contract call to the `setup_pools` endpoint by decoding our `msg` using a [Base64 decoder](https://www.base64decode.org/).
```json
[
{
{
"wasm": {
"execute": {
"contract_addr": "terra1gc4d4v82vjgkz0ag28lrmlxx3tf6sq69tmaujjpe7jwmnqakkx0qm28j2l", // generatorAddress
"msg": "ewogICJzZXR1cF9wb29scyI6IHsKICAgICJwb29scyIgOiBbCiAgICAgIFsKICAgICAgICAidGVycmExOG1jbWxmNHYyM2VodWtraDdxeGdwZjV0em56ZzY4OTNmeG1mOWZmbWR0OXBoZ2YzNjV6cXZtbHVnNiIsCiAgICAgICAgIjE1MzgiCiAgICAgIF0sCiAgICAgIFsKICAgICAgICAidGVycmExNmVzams3cXFsZ2g4dzdwMmE1OHl4aGdrZms0eWt2NzJwN2hhMDU2enVsNThhZHpqbTZtc3ZjNjc0dCIsCiAgICAgICAgIjMwMDE4IgogICAgICBdLAogICAgICBbCiAgICAgICAgInRlcnJhMWNrbXNxZGhsa3k5anhjbXR5ajY0Y3Jnemp4YWQ5cHZzZDU4azh6c3hzbnY0dnp2d2R0N3FrZTA0aGwiLAogICAgICAgICI0MDAyNiIKICAgICAgXSwKICAgICAgWwogICAgICAgICJ0ZXJyYTFrZ2dmZDZ6MGFkMms5cTh2MjRmN2Z0eHlxdXNoOGZwOXhrdTlueXJqY3Myd3YwZTRreXBzemZyZmQwIiwKICAgICAgICAiNjY2NiIKICAgICAgXSwKICAgICAgWwogICAgICAgICJ0ZXJyYTFjcTIyZXVneHdncDB4MzRjcWZyeG1kOWpreXk0M2dhczkzeXFqaG13cm03ajBoNWVjcnFxNWo3ZGdwIiwKICAgICAgICAiNjY2NiIKICAgICAgXSwKICAgICAgWwogICAgICAgICJ0ZXJyYTFraHN4d2ZuenV4cWN5emEyc3JheGYybmdrcjNkd3k5ZjdybTB1dHMweHBrZXNoczk2Y2NzcXR1Nm52IiwKICAgICAgICAiMTEyNTciCiAgICAgIF0sCiAgICAgIFsKICAgICAgICAidGVycmExaDN6Mnp2NmF3OTRmeDUyNjNkeTZ0Z3o2Njk5a3htZXdseDN2cmN1NGpqcnVkZzZ4bXR5cWs2dnQwdSIsCiAgICAgICAgIjY2NjYiCiAgICAgIF0sCiAgICAgIFsKICAgICAgICAidGVycmExY2VzNms2anA3cXpranB3c2w2eGc0Zjd6ZndyZTB1MjNjZ2xnNjloaGozZzIwZmh5Z3Rwc3UyNGRzeSIsCiAgICAgICAgIjIxNTIiCiAgICAgIF0KICAgIF0KICB9Cn0=",
"funds": []
}
}
}
}
]
```
</CH.Scrollycoding>
</CH.Section>
Before continuing with this section, make sure to read the section above on adjusting allocation points through the Astroport Web App. The Astroport Web App essentially wraps our executable message (covered above) within a submit_proposal
message to the Assembly
contract. This section will focus on completing this last step.
<CH.Section> <CH.Scrollycoding>
### `send`
To submit a proposal, you need to execute a contract call pointing to the [`send`](https://docs.rs/cw20/latest/cw20/enum.Cw20ExecuteMsg.html#variant.Send) endpoint in the xASTRO token contract.
The send operation takes in a:
- `contract` - Address where xASTRO tokens are being sent to (Assembly address)
- `amount` - Amount to send/stake (30,000 xASTRO for mainnet)
- `msg` - Binary encoded message containing our contract call to `submit_proposal`
```json
{
"send": {
"contract": assemblyAddress,
"amount": "1000", // testnet deposit amount
"msg": toBase64(
{
"submit_proposal": {
"title": "update astro emissions",
"description": "proposal to adjust astro allocation points inactive pair",
"link": "https://forum.astroport.fi/",
"messages": [
{
{
"wasm": {
"execute": {
"contract_addr": generatorAddress,
"msg": "ewogICJzZXR1cF9wb29scyI6IHsKICAgICJwb29scyIgOiBbCiAgICAgIFsKICAgICAgICAidGVycmExOG1jbWxmNHYyM2VodWtraDdxeGdwZjV0em56ZzY4OTNmeG1mOWZmbWR0OXBoZ2YzNjV6cXZtbHVnNiIsCiAgICAgICAgIjE1MzgiCiAgICAgIF0sCiAgICAgIFsKICAgICAgICAidGVycmExNmVzams3cXFsZ2g4dzdwMmE1OHl4aGdrZms0eWt2NzJwN2hhMDU2enVsNThhZHpqbTZtc3ZjNjc0dCIsCiAgICAgICAgIjMwMDE4IgogICAgICBdLAogICAgICBbCiAgICAgICAgInRlcnJhMWNrbXNxZGhsa3k5anhjbXR5ajY0Y3Jnemp4YWQ5cHZzZDU4azh6c3hzbnY0dnp2d2R0N3FrZTA0aGwiLAogICAgICAgICI0MDAyNiIKICAgICAgXSwKICAgICAgWwogICAgICAgICJ0ZXJyYTFrZ2dmZDZ6MGFkMms5cTh2MjRmN2Z0eHlxdXNoOGZwOXhrdTlueXJqY3Myd3YwZTRreXBzemZyZmQwIiwKICAgICAgICAiNjY2NiIKICAgICAgXSwKICAgICAgWwogICAgICAgICJ0ZXJyYTFjcTIyZXVneHdncDB4MzRjcWZyeG1kOWpreXk0M2dhczkzeXFqaG13cm03ajBoNWVjcnFxNWo3ZGdwIiwKICAgICAgICAiNjY2NiIKICAgICAgXSwKICAgICAgWwogICAgICAgICJ0ZXJyYTFraHN4d2ZuenV4cWN5emEyc3JheGYybmdrcjNkd3k5ZjdybTB1dHMweHBrZXNoczk2Y2NzcXR1Nm52IiwKICAgICAgICAiMTEyNTciCiAgICAgIF0sCiAgICAgIFsKICAgICAgICAidGVycmExaDN6Mnp2NmF3OTRmeDUyNjNkeTZ0Z3o2Njk5a3htZXdseDN2cmN1NGpqcnVkZzZ4bXR5cWs2dnQwdSIsCiAgICAgICAgIjY2NjYiCiAgICAgIF0sCiAgICAgIFsKICAgICAgICAidGVycmExY2VzNms2anA3cXpranB3c2w2eGc0Zjd6ZndyZTB1MjNjZ2xnNjloaGozZzIwZmh5Z3Rwc3UyNGRzeSIsCiAgICAgICAgIjIxNTIiCiAgICAgIF0KICAgIF0KICB9Cn0=",
"funds": []
}
}
}
}
],
"ibc_channel": "channel..."
}
}
),
}
}
```
---
### `submit_proposal`
Our encoded message performs a contract call to the [`submit_proposal`](../../develop/smart-contracts/astral-assembly#submit_proposal) endpoint in the [`Assembly`](../../develop/smart-contracts/astral-assembly) contract.
`submit_proposal` takes in the following parameters:
- `title`: Proposal title
- `description`: Description for the proposal
- `link`: Link to forum discussion
- `messages`: Proposal message containing our binary contract call to `setup_pools`
- `ibc_channel`: If the proposal should be executed on a remote chain, this field should specify the governance channel
All further steps to the `messages` parameter can be found [above](#using-the-astroport-web-app).
```json focus=6:26
```
---
### Encoding our `submit_proposal` `msg`
Finally, our `submit_proposal` message needs to be encoded and passed as an input into our msg parameter within our `send` call.
```json focus=5:27
```
---
#### `toBase64`
The code in this section uses a custom function (`toBase64`) to display our binary message - this function needs to be defined elsewhere to be used. The actual string representation of our message would be an encoded binary, similar to our `setup_pools` message.
```js
let toBase64 = (obj) => {
return Buffer.from(JSON.stringify(obj)).toString("base64");
};
```
</CH.Scrollycoding>
</CH.Section>
{/*
<CH.Scrollycoding>
Before we dive in, it's generally a good idea to list all contract addresses that we will be using in our code. For fine-tuning pool allocation points, a proposal will interact with 3 contracts: the Assembly, Generator, and xASTRO contracts. For a full list of mainnet and testnet addresses, visit the Github changelog.
// contract addresses (testnet)
const assembly_address = 'terra195m6n5xq4rkjy47fn5y3s08tfmj3ryknj55jqvgq2y55zul9myzsgy06hk';
const xastro_address = 'terra1ctzthkc0nzseppqtqlwq9mjwy9gq8ht2534rtcj3yplerm06snmqfc5ucr';
const generator_address = 'terra1ksvlfex49desf4c452j6dewdjs6c48nafemetuwjyj6yexd7x3wqvwa7j9';
// base64 encoder
function toEncodedBinary(object) {
return Buffer.from(JSON.stringify(object)).toString('base64');
}
// setup_pools_msg
const setup_pools_msg = {
"setup_pools": {
"pools": [
("lp_token_address", "1000"),
("lp_addr2", "10"),
... etc
]
}
}
const binary = toEncodedBinary(setup_pools_msg)
const proposal_msg = [
{
order: "1",
msg: {
wasm: {
execute: {
contract_addr: generator_address,
msg: binary,
funds: []
}
}
}
}
]
// submit_proposal_msg
const submit_proposal_msg = {
"submit_proposal": {
"title": "testing",
"description": "testing",
"link": null,
"messages": proposal_msg
}
}
const binary2 = toEncodedBinary(submit_proposal_msg)
const proposal_msg2 = {
"send": {
"contract": assembly_address,
"amount": "30000000000",
"msg": binary2
}
}
We will need to encode and nest several messages. For this guide, we will be using a custom function that will encode and pass our messages.
There are two common mistakes to look for when crafting the setup_pools
endpoint:
- The message expects LP token addresses, not pair addresses!
- The message expects a vector of LP contract addresses. Specifying a single address rewrites all active pools with the pools specified in the message.
You can query the generator contract to include previous LP token addresses and allocation points.
Note: In some cases, the community may want to decrease allocation points for particular pools, thus proposal submitters have to mutate config.active_pools list.
let config = await terra.wasm.contractQuery(terra, network.generatorAddress, {config: {}})
config.active_pools.push(("new_lp_token", "new_alloc_points"))
const generator_msg = {
"setup_pools": {
"pools":
("lp_token_address", "1000"),
config.active_pools
}
}
We use our toEncodedBinary
function to encode our message and pass it into our proposal_msg
variable along with our generator_address
.
// contract addresses (testnet)
const assembly_address = 'terra195m6n5xq4rkjy47fn5y3s08tfmj3ryknj55jqvgq2y55zul9myzsgy06hk';
const xastro_address = 'terra1ctzthkc0nzseppqtqlwq9mjwy9gq8ht2534rtcj3yplerm06snmqfc5ucr';
const generator_address = 'terra1ksvlfex49desf4c452j6dewdjs6c48nafemetuwjyj6yexd7x3wqvwa7j9';
// base64 encoder
function toEncodedBinary(object) {
return Buffer.from(JSON.stringify(object)).toString('base64');
}
// setup_pools_msg
const setup_pools_msg = {
"setup_pools": {
"pools": [
("lp_token_address", "1000"),
("lp_addr2", "10"),
... etc
]
}
}
const binary = toEncodedBinary(setup_pools_msg)
const proposal_msg = [
{
order: "1",
msg: {
wasm: {
execute: {
contract_addr: generator_address,
msg: binary,
funds: []
}
}
}
}
]
// submit_proposal_msg
const submit_proposal_msg = {
"submit_proposal": {
"title": "testing",
"description": "testing",
"link": null,
"messages": proposal_msg
}
}
const binary2 = toEncodedBinary(submit_proposal_msg)
const proposal_msg2 = {
"send": {
"contract": assembly_address,
"amount": "30000000000",
"msg": binary2
}
}
The submit_proposal_message
variable contains general information regarding our proposal, such as our proposal’s title, description, link, and the proposal_msg
array we defined above. If this proposal message seems familiar to you, it’s because it is! These fields are used in the Astroport web app to submit a proposal using a user-friendly UI.
Our final message will call the send
function in the xASTRO contract. This message requires the address of the contract that we are sending xASTRO to (assembly_address
), the amount of ASTRO to send (30,000 ASTRO required for a proposal), and a msg field with our proposal binary from above.
</CH.Scrollycoding>
Once a proposal has been submitted, it will go through the standard governance process.
*/}