Create Proxy Wallet
Last updated
Last updated
In Vortex we created fully non-custodial architecture, where only you have access to assets. To achieve this we created deterministic scheme to create proxy wallets.
To generate wallets you can use #calculate-address on Curra API, and verify that this address belongs to your Ownership ID with #how-to-calculate-address-to-verify, so assets from these wallets can be transferred only to your Ombibus wallets, whitelisted in Rules smart contract, ensuring security of your assets.
Every address is generated from unique salt (can be considered an unique identifier) and addresses remain the same across different EVM chains if their salts are equal. This means you can create the same addresses across multiple EVM blockchains.
Addresses are fully deterministic and non-custodial. address is used as seed. After is minted, addresses become immutable (this happens when first deposit is forwarded to Omnibus wallet) and only the NFT holder can change the
Address calculation can defer on different platform / programming languages, but general algorithm is the following:
Calculate identifier:
gasPumpAddress = "0x............"
presetsAddress = "0x............"
ownershipId = uint256(keccak256(abi.encodePacked(address(presetsAddress), keccak256(abi.encodepacked(gasPumpAddress)))))
Calculate Rule upgradable proxy address:
// abi is predictProxyAddress(uint256), proxy address is upgradable proxy of the Rule smart contract
proxyAddress = curraContract.predictProxyAddress(ownershipId)
Calculate forwarder implementation address which is going to be used to generate clones, aka proxy wallets
forwarderImplInitcode = "60a03461008b57601f61082c38819003918201601f19168301916001600160401b038311848410176100905780849260209460405283398101031261008b57516001600160a01b038116810361008b5760805260405161078590816100a7823960805181818160880152818160e801528181610172015281816101fc0152818161027d01526103c40152f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe6080806040526004361015610022575b50361561001857005b61002061036b565b005b600090813560e01c90816325e3d522146102335750806358843b36146101ad5780637d76ccf114610117578063b41b08c2146100c15763d87108d00361000f57346100be57610070366102c9565b9073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036100ba576100b79261062d565b80f35b8380fd5b80fd5b50346100be576100d0366102c9565b9073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036100ba576100b792610554565b50346100be5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100be5761014f6102a1565b60643573ffffffffffffffffffffffffffffffffffffffff80821682036100ba577f00000000000000000000000000000000000000000000000000000000000000001633036101a9576100b79160443590602435906106bc565b8280fd5b50346100be5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100be576101e56102a1565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361022f576100b7906024359061052e565b5080fd5b90503461022f57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022f5760209073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b6004359073ffffffffffffffffffffffffffffffffffffffff821682036102c457565b600080fd5b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60609101126102c45773ffffffffffffffffffffffffffffffffffffffff60043581811681036102c457916024359160443590811681036102c45790565b67ffffffffffffffff811161033c57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604080517f8fab1a0600000000000000000000000000000000000000000000000000000000815230600482015247602482015260006044820181905273ffffffffffffffffffffffffffffffffffffffff9083836064817f000000000000000000000000000000000000000000000000000000000000000086165afa9283156104b45781948294610410575b50505082161561040c5761040a916104c0565b565b5050565b919450919250803d82116104ad575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f820116830183811067ffffffffffffffff8211176104805782528201829003126101a95780519282841684036100be575060200151903880806103f7565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b503d61041f565b508351903d90823e3d90fd5b600080809381935af1156104d057565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152fd5b9073ffffffffffffffffffffffffffffffffffffffff82161561040c5761040a916104c0565b91909173ffffffffffffffffffffffffffffffffffffffff80921680156106275760008093604493602096604051947fa9059cbb00000000000000000000000000000000000000000000000000000000865260048601526024850152165af13d15601f3d11600160005114161716156105c957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152fd5b50505050565b909173ffffffffffffffffffffffffffffffffffffffff809116918215610627571691823b156102c45760646000928360405195869485937f42842e0e000000000000000000000000000000000000000000000000000000008552306004860152602485015260448401525af180156106b0576106a75750565b61040a90610328565b6040513d6000823e3d90fd5b919273ffffffffffffffffffffffffffffffffffffffff8091169283156107485716803b156102c4576000928360c49260405196879586947ff242432a00000000000000000000000000000000000000000000000000000000865230600487015260248601526044850152606484015260a060848401528160a48401525af180156106b0576106a75750565b505050505056fea26469706673582212207adce9e6f6f4860d32d895a3080819821d79bea7e3699d0e3d8c4deb4aae60d064736f6c63430008120033"
const forwarderImplementationAddress = getCreate2Address(
ownershipNFTAddress, // deployer
ownershipId, // salt
forwarderImplInitcode, // initcode
);
Calculate proxy wallet address:
salt = "0000000000000000" // 8 byes
forwarderImplAddressBytes = strip0x(forwarderImplementationAddress)
proxyInitcode = `0x602c3d8160093d39f33d3d3d3d363d3d37363d73${forwarderImplAddressBytes}5af43d3d93803e602a57fd5bf3`;
proxyInitcodeHash = keccak256(proxyInitcode);
forwarderAddress = getCreate2Address(
proxyAddress,
salt,
proxyInitcodeHash,
);
forwarderAddress
is the address of the proxy wallet.
POST
https://api.curra.io/addresses
This method uses random salt
to calculate next address.
content-type*
application/json
x-api-key*
your_api_key
blockchains*
string[]
["ETHEREUM", "SMART_CHAIN", "POLYGON", "GOERLI"]
uniqueId
string
minLength: 1, maxLength: 100
meta
string
minLength: 1, maxLength: 500
[
{
"value": "string",
"id": "string",
"blockchain": "ETHEREUM",
"uniqueId": "string",
"meta": "string",
"timestamp": 0
}
]
{
"message": "string",
"error": "ADDRESSES_ARE_DIFFERENT"
}
import { Blockchain } from "@curra/sdk";
// just new addresses
// NOTICE: returns two identical addresses created in two different EVM blockchains
const addresses = await curra.createAddresses({
blockchains: [Blockchain.ETHEREUM, Blockchain.SMART_CHAIN],
});
// new address with additional fields
const [address] = await curra.createAddresses({
blockchains: [Blockchain.ETHEREUM],
uniqueId: "I'm unique", // optional unique id
meta: "my user id?", // custom data can be linked to the address, will be included in incomes webhooks
});