Introduction
Before starting to use near-multicall for making DAO proposals, we first need to establish a general understanding of how it works.
The multicall instance (MI)
The regular DAO contract (SputnikDAO) can only call one target contract per proposal. That's why for proposals that call multiple smart contracts, we need a proxy contract that will handle all desired function calls. Multicall instances serve this purpose. Every DAO has its own private multicall instance to work with.
In a multicall proposal, the DAO calls its MI and passes it some instructions, the MI will follow those instructions to call the desired functions on the target contracts.
The MI address is always derived from the DAO address. It's easy to explain it with an example:
If the DAO address is marmaj.sputnik-dao.near
then it will have a MI deployed at marmaj.v1.multicall.near
DAOs need to create a multicall instance (MI) before using it for the first time. You can think of this as an installation step that only happens once. Instructions for this can be found on the onboarding guide.
Onboard your DAO
In order to create a multicall instance for your DAO, you must have permissions to create function-call proposals on the DAO.
- Go to https://multicall.app/#/dao
- In the lower left hand corner log in with your wallet (1.) and select the DAO you would like to use multicall with (2.).
If the DAO symbol lights up red, the address is not a valid dao address - please check for typos. Instead the symbol should be yellow, indicating that while the DAO exists, there is no belonging multicall instance yet.
- In the middle of the page you see requirements that need to be met in order to create a multicall instance for the specified dao. If all except "DAO has no multicall instance" are met, a green button shows up, click it to propose a multicall creation proposal.
The website will also show a blue button, if a creation proposal already exists, click it to vote yes (You can also vote using AstroDAO).
- Once the proposal passes, a multicall instance will be deployed to [dao‑name].v1.multicall.near. If a multicall instance exists for the chosen DAO, the website will display its state, such as whitelisted tokens and job bond.
Make a multicall proposal
Our website offers a space to build your proposals. Simply drag a card from the side menu into the column in the middle of the page. This column will contain the instructions given to the Multicall Instance (MI), and they are executed in sequence from top to bottom. For advanced usage, you can add more columns by clicking the + icon on top of the columns. The instructions in all columns will run concurrently.
Let's talk a little about the cards. Cards serve as building blocks of the proposal. They hold information about what contract and function to call with what parameters. Click the pen icon ( edit) in the top right corner of a card to open the card's editor where you specify the required parameter. Any interaction can be modeled using the custom card, but we're always expanding our selection of cards for sepecific purposes to lower the technical barriers for users.
Think we're missing an important card? Let us know on our Discord !
Once you are satisfied with your proposal, click on the Export tab in the side menu. You will be asked to put a proposal description that will be displayed on AstroDao. If everything is fine, i.e. you don't have any unresolved input errors and you have the rights to make proposals on the DAO, the propose button at the bottom of the menu will turn green. Click it to make the proposal on the DAO.
A small amount of NEAR will be required to make the transaction. It represents a proposal bond paid to the DAO, and will be reimbursed once your DAO proposal is approved. The amount is set in the DAO configuration, near-multicall does not charge any fees.
Dealing with funds
As we have seen in The multicall instance the MI serves as a proxy contract for the DAO. Since the DAO and MI are not the same contract, the MI cannot access funds belonging to the DAO. This is a good thing when it comes to security, but does bring some inconveniences. Any funds that are need for a multicall proposal should be transferred to the MI prior to the execution of said proposal. We suggest to have a small tokens' allowance on the MI for quick access, while keeping the main DAO's treasury on the DAO. The funds on the MI are only accessible by the MI admins (per default, only the DAO).
Near-multicall is a beta software and we do not guarantee the safety of assets on the MI. Our contracts are open source, and can be found on this repository. Use at your own risk.
You can easily see the available funds on the MI via the Funds tab on the DAO page.
When making a multicall proposal, keep in mind that the actions will be called from the MI's address, and not the DAO address. Say you want to interact with a Dapp, it will be the MI's Dapp account that is used, not the DAO's.
View a multicall proposal
After creating a proposal, the next step is for other DAO members to review it and vote on it. However, the way multicall proposals are displayed on AstroDAO (or other generic DAO frotends) isn't human-friendly. As an example, can you tell what the following proposal does?
Visualizing proposals
It is really important to understand proposals before voting on them. Hence, the need to parse their arguments and display them in a more intuitive way. You can use the multicall UI to visualize a proposal by just copying the proposal's link and pasting it into the "load from proposal" dialog. The following GIF demonstrates that:
We currently support proposal links from both AstroDAO and the base Sputnik UI. We're also open to supporting more UIs as well, so send us your suggestions!
Another use case for this feature is the creation of templates: If you want to create a proposal that's very similar to another proposal that you or someone else made in the past (regardless of which DAO it happened on), then why start from scratch? Instead, load the old proposal and apply your changes on top of it.
DAO login
Near-multicall allows DAOs to interact more freely with other DApps on NEAR. However, it's not always easy to see the results of these interactions. DApp interfaces provide invaluable information to their users, such as:
- Overview of Defi positions
- View into pending or unclaimed rewards
- Usage history and statistics
Hence the need for DAO members to login into DApps using their DAO's address.
Here's how to do it:
- Open the DApp to be used. Example: Ref-finance
- If you're already logged in with your personal wallet there, Log out.
- On Ref, click login, choose NEAR wallet, and then close that tab.
- Open Multicall on a seperate tab.
- Click the DAO/Multicall login dialog.
- Paste the DApp URL in the input field.
- Click on Proceed.
Here's a GIF going over the same steps using Ref-finance
- This only works with DApps that support either NEAR wallet or MyNearWallet
- Login will be in "read-only" mode, so the DAO's account will not initiate transactions using the DApp's interface
Smart contracts
The project has 2 contracts: the Multicall Instance (MI) and a factory contract for spinning-up instances. Both contracts are written using AssemblyScript and are open-source. Code can be found on our contracts repository.
Deployments
NEAR Mainnet
Contract | Address | Code hash |
---|---|---|
Factory | v1.multicall.near | 2Y3VuVZTPaXGBnRj6Av9ymKM17iSGv1b1xJTsdkrmSFh |
NEAR Testnet
Contract | Address | Code hash |
---|---|---|
Factory | v1_03.multicall.testnet | 2Y3VuVZTPaXGBnRj6Av9ymKM17iSGv1b1xJTsdkrmSFh |
The factory contract
The main method on the factory contract is create()
. It must be called from a DAO using a FunctionCall proposal.
Here's the singature of the method:
export function create(
multicall_init_args: {
admin_accounts: string[];
croncat_manager: string;
job_bond: u128;
},
public_key: string = ""
): ContractPromiseBatch
admin_accounts
: a list of NEAR accounts that will have absolute control over the instance, including its funds. We recommend that only the DAO is included here so the created instance only executes instructions approved by the DAO.croncat_manager
: address of the Croncat manager contract. It is used by our scheduling features.job_bond
: the job bond is the $NEAR amount to be paid by users wishing to submit scheduled multicall proposals to the DAO. The proposer will be re-imbursed upon approval of his proposal. By default we set it to be equal to the DAO's proposal bond.public_key
: this is optional. When provided, this key will added as a fullAccess key on the multicall instance.
The instance contract
This contract holds the core logic for multicall. Each DAO gets its own Multicall Instance (MI) contract to use. The contract consists of three main features:
-
The main method in this contract is:
multicall ( calls: BatchCall[][] )
It executes a bunch ofBatchCall
arrays.
EachBatchCall
has information for making a batch of function-calls: a target address and an array on function-calls to execute on that target. Each function-call has a function name, arguments encoded in base64, gas to use (u64 encoded as string) and amount of yoctoNEAR attached deposit (u128 encoded as string).
Batches inside one array run one after another, as a promise chain.
Different arrays of batches run in parallel.
Example:calls = [ [ Batch_11, Batch_12, Batch_13 ], [ Batch_21, Batch_22] ]
In this example we have 2 arrays of batches. In the first one
Batch_12
waits forBatch_11
andBatch_13
waits forBatch_12
. In the second arrayBatch_22
waits forBatch_21
. Both arrays start executing in the same block and are independent of each other. -
Permissioned interactions with the contract through whitelisting of addresses:
Due to the async nature of Near, funds can sit in the contract during multiple blocks awaiting the execution of cross-contract calls. To prevent stealing of funds, we require an address to be whitelisted before calling one of the contract's critical methods. there are two main whitelists:
admins whitelist
holds addresses that can interact with the contract, they can add or remove others from the whitelist.
tokens whitelist
holds token addresses that can be attached to function calls, as the contract implements ft_on_transfer.
The contract's address is whitelisted by default, this allows nesting multiple contract methods for convenience. -
Jobs:
Multicall executions can be scheduled to run at a certain time in the future, made possible by integrating croncat. Anyone can register a job on the multicall contract, but an admin has to approve it. Admins can pause/resume job executions and also edit a job's multicall arguments.
The following must be specified when creating a job:function job_add ( job_multicalls: MulticallArgs[], job_cadence: string, // cron expression job_trigger_gas: u64, job_total_budget: u128, job_start_at: u64 = context.blockTimestamp ): u32
Example Calls
Call structure
example multicall arguments:
{
"calls": [
[
{
"address": "hello.lennczar.testnet",
"actions": [
{
"func": "hello",
"args": "eyJ0aGluZyI6IldvcmxkIn0=", // base64 encoding for {"thing":"World"}
"gas": "10000000000000",
"depo": "0"
},
{
"func": "hello",
"args": "eyJ0aGluZyI6IldvcmxkIn0=", // base64 encoding for {"thing":"World"}
"gas": "10000000000000",
"depo": "0"
}
]
},
{
"address": "hello.lennczar.testnet",
"actions": [
{
"func": "hello",
"args": "eyJ0aGluZyI6IldvcmxkIn0=", // base64 encoding for {"thing":"World"}
"gas": "10000000000000",
"depo": "0"
}
]
}
],
[
{
"address": "hello.lennczar.testnet",
"actions": [
{
"func": "hello",
"args": "eyJ0aGluZyI6IldvcmxkIn0=", // base64 encoding for {"thing":"World"}
"gas": "10000000000000",
"depo": "0"
}
]
}
]
]
}
This example calls the function hello(thing: string): string
in the contract hello.lennczar.testnet
.
We see two arrays of batches: in the first array we have 2 batches that will be run as a promise chain (i.e. second batch will wait for the first batch). The first batch calls the function twice and the second batch calls it only once. In the second array we have one batch that calls the function once, it will run in parallel independently of the two previously mentioned batches.
Running this results in the following transaction
Important links:
- Website (Mainnet): https://multicall.app
- Website (Testnet): https://testnet.multicall.app
- GitHub: https://github.com/near-multicall
- Twitter: https://twitter.com/near_multicall
- Discord: https://discord.gg/wc6T6bPvdr