The Portal Contract
Portal Deployment
Toshi Mart is based on Flap Protocol V4 with an optional farcaster extension. The entrypoint of the protocol is a smart contract named Portal
, all transactions and interactions with the Toshi Mart are routed through this contract.
The Portal contract is deployed on both Base Mainnet and Base Sepolia Testnet. The contract address is as follows:
Base Mainnet
0x1ea172Fb88C24DFC21Ff6Fa38762511C123bA948
Base Sepolia Testnet
0x561e4410DD8d4428Fb43127F1B19488F33523810
The portal entrypoint is verified on basescan.The interface and abi of the Portal contract can be found on basescan.
1. How To Launch A Token on Toshi Mart
1.1 Prepare The Metadata For Your Token
Toshi Mart assumes your token's metadata is stored on IPFS. The following is an example of the metadata for a token:
{
"buy": null,
"creator": "0x315F3803d4b33F9316be52297522EA7208a52f80",
"description": "#JACKWILLTAKEUS ",
"image": "bafkreic7gc6krk32vmtvd55f3n2wavevz6hcxsyeagxppgn3p2gwphafsi",
"sell": null,
"telegram": null,
"twitter": null,
"website": null
}
Note the image
field is another IPFS hash of the image you want to use as the token's image.
Although you can use any IPFS gateway to upload and pin your metadata, we recomend using our upload endpoint for uploading the metadata json along with the image in a single request. Here is an typescript example of how to upload the metadata and image to Toshi Mart's upload endpoint:
/// Upload the meta of the token
async function uploadTokenMeta(cfg: {
buy: string | null;
creator: string;
description: string;
sell: string | null;
telegram: string | null;
twitter: string | null;
website: string | null;
image_path: string;
}) {
const form = new FormData();
const MUTATION_CREATE = `
mutation Create($file: Upload!, $meta: MetadataInput!) {
create(file: $file, meta: $meta)
}
`;
form.append(
"operations",
JSON.stringify({
query: MUTATION_CREATE,
variables: {
file: null, meta: {
website: cfg.website,
twitter: cfg.twitter,
telegram: cfg.telegram,
description: cfg.description,
creator: "0x0000000000000000000000000000000000000000",
}
},
})
);
form.append(
"map",
JSON.stringify({
"0": ["variables.file"],
})
);
// read local file and convert to File object, with type "image/png"
const file = new File([fs.readFileSync(cfg.image_path)], "image.png", {
type: "image/png",
});
form.append("0", file);
const res = await axios.postForm("https://beta-api.rcto.fun/", form, {
headers: {
"Content-Type": "multipart/form-data",
},
});
if (res.status !== 200) {
throw new Error(`failed to upload the token meta: ${res.statusText}`);
}
console.log("token meta uploading response: ", res.data);
// the cid is in the response data
const cid = res.data.data.create;
return cid;
}
1.2 Find The Vanity Salt
Every token launched on Toshi Mart now has a vanity ending: every token's CA ends with 8453
. The salt for getting the vanity ending for your token contract should be provided on calling the newTokenV3
method of the Portal contract.
The resulting address of the token depends on the token_impl
address. Every token contract launched on Toshi Mart is a clone of the token_impl
contract, the token_impl
contract is deployed on Base Mainnet and Base Sepolia Testnet. The contract address is as follows:
Base Mainnet
0xF3c514E04f83166E80718f29f0d34F206be40A0A
Base Sepolia Testnet
0x3B77b7AE7d925E59a346b0b552Bb6e4BEf417863
Here is a typescript example of how to find the vanity salt for your token to be launched on Toshi Mart:
import { Account, Address, createWalletClient, encodeAbiParameters, encodeDeployData, encodeFunctionData, formatEther, getContract, getContractAddress, Hex, hexToBigInt, http, keccak256, parseEther, parseGwei, parseTransaction, PublicClient, serializeTransaction, toBytes, toHex } from 'viem';
// mainnet info
const portal = "0x1ea172Fb88C24DFC21Ff6Fa38762511C123bA948" as Address;
const token_impl = "0xF3c514E04f83166E80718f29f0d34F206be40A0A" as Address;
/// get vanity token address and salt
async function findVanityTokenSalt(suffix: string) {
if (suffix.length !== 4) {
throw new Error("Suffix must be exactly 4 characters");
}
// predict the vanity token address based on the salt
const predictVanityTokenAddress = (salt: Hex): Address => {
const bytecode = '0x3d602d80600a3d3981f3363d3d373d3d3d363d73'
+ token_impl.slice(2).toLowerCase() // remove 0x prefix
+ '5af43d82803e903d91602b57fd5bf3' as Hex;
return getContractAddress({
from: portal,
salt: toBytes(salt),
bytecode,
opcode: "CREATE2",
});
}
// Note: you don't have to use a private key as the starting seed, you can use
// any pseudo-random string as the starting seed.
//
// Here, we use a random private key as the starting seed
// Then repeatedly hash the seed until we get the vanity address
const seed = generatePrivateKey();
let salt = keccak256(toHex(seed));
let iterations = 0; // Track the number of iterations
while (!predictVanityTokenAddress(salt).endsWith(suffix)) {
salt = keccak256(salt);
iterations++; // Increment the iteration count
}
console.log(`Iterations: ${iterations}`); // Print the number of iterations
return {
salt,
address: predictVanityTokenAddress(salt),
}
}
1.3 Send The Transaction To Launch The Token
To launch a token on Toshi Mart, you need to call the newTokenV3
method of the Portal contract in a transaction. The newTokenV3
method takes a NewTokenV3Params
struct as the parameter, which contains the following fields:
name
: The name of the token, e.g.The Test Token
symbol
: The symbol of the token, e.g.TEST
meta
: this is the ipfs cid you get from last section , eg,bafkreic7gc6krk32vmtvd55f3n2wavevz6hcxsyeagxppgn3p2gwphafsi
dexThresh
: This determines the threshold to migrate token to DEX. Our UI usesFOUR_FIFTHS
by default, which means when 80% or more of the total supply has been sold from the bonding curve , the token will be migrated to DEX.taxRate
: for Toshi Mart, this must always be 0.migratorType
: The migrator for the token. Our UI usesV3_MIGRATOR
by default. With aV3_MIGRATOR
we will optimize your liquidity and enable the revenue share feature for your token.quoteToken
: The quote token you want to use. When your quote token is the native gas token (i.e ETH), leave quoteToken as the zero address. Note: only enabled quoteToken can be used.quoteAmt
: The amount of quoteToken you want to spend to buy token on creation.beneficiary
: If the token uses aV3_MIGRATOR
, the LP fee can later be claimed with this address after the token is migrated to DEX.permitData
: If your quoteToken is not zero address (i.e, not native gas token ETH , but some ERC20 token). You can construct thepermitData
to avoid another approve TX. Unluckily, TOSHI token does not support permit yet, so you need to approve TOSHI token before calling thenewTokenV3
method. However, we may add other tokens as quote tokens in the future, so you can use thepermitData
to avoid another approve TX.salt
: The salt is mandate. All tokens created on Toshi Mart will have a vanity ending8453
, so you need to provide the salt that will generate the vanity ending. You can use thefindVanityTokenSalt
function in the previous section to get the salt.extensionID
: check the1.4 A Note On The Extension
section for more details on how to use the extension. If your payment token is TOSHI, this should never be empty.extensionData
: check the1.4 A Note On The Extension
section for more details on how to use the extension. If you are not using any extension, this can be empty.
/// @notice Create a new token (V3) with extension support
/// @param params The parameters for the new token including extension configuration
/// @return token The address of the created token
/// @dev Similar to newTokenV2 but with extension support. Extension hooks will be called if extensionID is non-zero
function newTokenV3(NewTokenV3Params calldata params) external payable returns (address token);
/// @notice Parameters for creating a new token (V3) with extension support
struct NewTokenV3Params {
/// The name of the token
string name;
/// The symbol of the token
string symbol;
/// The metadata URI of the token
string meta;
/// The DEX supply threshold type
DexThreshType dexThresh;
/// The salt for deterministic deployment
bytes32 salt;
/// The tax rate in basis points (if non-zero, this is a tax token)
uint16 taxRate;
/// The migrator type (see MigratorType enum)
MigratorType migratorType;
/// The quote token address (native gas token if zero address)
address quoteToken;
/// The initial quote token amount to spend for buying
uint256 quoteAmt;
/// The beneficiary address for the token
/// For rev share tokens, this is the address that can claim the LP fees
/// For tax tokens, this is the address that receives the tax fees
address beneficiary;
/// The optional permit data for the quote token
bytes permitData;
/// @notice The ID of the extension to be used for the new token if not zero
bytes32 extensionID;
/// @notice Additional extension specific data to be passed to the extension's `onTokenCreation` method, check the extension's documentation for details on the expected format and content.
bytes extensionData;
}
/// @notice the migrator type
/// @dev the migrator type determines how the liquidity is added to the DEX.
/// Note: To mitigate the risk of DOS, if a V3 migrator is used but the liquidity cannot
/// be added to v3 pools, the migrator will fallback to a V2 migrator.
/// A TAX token must use a V2 migrator.
enum MigratorType {
V3_MIGRATOR, // Migrate the liquidity to a Uniswap V3 like pool
V2_MIGRATOR // Migrate the liquidity to a Uniswap V2 like poo
}
/// @dev dex threshold types
enum DexThreshType {
TWO_THIRDS, // 66.67% supply
FOUR_FIFTHS, // 80% supply
HALF, // 50% supply
_95_PERCENT, // 95% supply
_81_PERCENT, // 81% supply
_1_PERCENT // 1% supply => mainly for testing
}
1.4 A Note On The Extension
The only supported extension for Toshi Mart is the Farcaster extension. The Farcaster extension allows you to attribute your actions (either launching a token or trading a token) to your Farcaster account (or the coming BASE app profile).
Currently, the extension does not support ETH pair. When your quote token is ETH (i.e zero address), both
extensionID
andextensionData
should be empty.If your quote token is TOSHI, the
extensionID
should be set to0xde2fc1e2b9af1e3b4c78aa33ffb29301a87cd6208fff491445490b8df8a4effa
and theextensionData
is optional. IfextensionData
is not empty, you can provide the proof and attribute it to your Farcaster account.
Check the Farcaster Extension
section for more details on how to use the Farcaster extension.
2. How To Trade A Token
2.1 Bonding Curve Fee
Currently, Toshi Mart charges a 1% fee on every trade on the bonding curve. The fee is taken from the quote token (i.e ETH or TOSHI).
That means if you buy 10000 TOSHI value of the token, only 9900 TOSHI will be added to the token's reserve, and 100 TOSHI will be taken as the fee. And if you sell 10000 TOSHI value of the token, only 9900 TOSHI will be sent to you, and 100 TOSHI will be taken as the fee.
2.2 Trade Migrated Tokens
Since v4.5.0, the portal contract has supported trades for migrated tokens. Fetching a quote and executing a swap are the same for both tokens that are still on the bonding curve and tokens that are already listed on Uniswap:
You can get a quote with
quoteExactInput
You execute the trade by calling the
swapExactInput
method
And the sugar swap is also available:
If a token's quote token is TOSHI, you can still swap ETH for that token or the other way around.
2.3 Get A Quote
To get a quote , we call the quoteExactInput
function of the Portal
contract.
/// @notice Parameters for quoting the output amount for a given input
struct QuoteExactInputParams {
/// @notice The address of the input token (use address(0) for native asset)
address inputToken;
/// @notice The address of the output token (use address(0) for native asset)
address outputToken;
/// @notice The amount of input token to swap (in input token decimals)
uint256 inputAmount;
}
/// @notice Quote the output amount for a given input
/// @param params The quote parameters
/// @return outputAmount The quoted output amount
/// @dev refer to the swapExactInput method for the scenarios
function quoteExactInput(QuoteExactInputParams calldata params) external returns (uint256 outputAmount);
Note: the quoteExactInput
method is not a view function, but we don’t need to send a transaction to get the quote (an eth_call
or the simulation in viem will do the work) .
If the quote token is ETH, we construct the QuoteExactInputParams
as follows:
If we are swapping ETH to the token, we set the inputToken
to address(0)
and the outputToken
to the token's address. And the inputAmount
is the amount of ETH we want to spend.
If we are swapping the token to ETH, we set the inputToken
to the token's address and the outputToken
to address(0)
. And the inputAmount
is the amount of token we want to sell.
If the quote token is TOSHI, we construct the QuoteExactInputParams
as follows:
If we are swapping TOSHI for the token, we set the inputToken
to the TOSHI token address and the outputToken
to the token's address. And the inputAmount
is the amount of TOSHI we want to spend.
If we are swapping the token to TOSHI, we set the inputToken
to the token's address and the outputToken
to the TOSHI token address. And the inputAmount
is the amount of token we want to sell.
Besides, we support a sugar swap
to pay ETH or receive ETH even when the quote token is TOSHI. Under the hood, we will swap ETH to TOSHI or TOSHI to ETH through Uniswap before or after executing the bonding curve swap.
2.4 Execute The Swap
After getting the quote, we can execute the swap by calling the swapExactInputV3
method of the Portal
contract. The swapExactInputV3
method takes an ExactInputV3Params
struct as the parameter, which contains the following fields:
inputToken
: This can either be any of the quote token (i.e zero address for ETH or TOSHI) or the token you want to trade. If you want to sell the token, set this to the token's address. If you want to buy the token, set this to the quote token's address (i.e zero address for ETH or TOSHI).outputToken
: This can either be any of the quote token (i.e zero address for ETH or TOSHI) or the token you want to trade. If you want to sell the token, set this to the quote token's address (i.e zero address for ETH or TOSHI). If you want to buy the token, set this to the token's address.inputAmount
: The amount of input token to swap. If you want to buy the token, this is the amount of quote token you want to spend. If you want to sell the token, this is the amount of token you want to sell.minOutputAmount
: The minimum amount of output token you want to receive. This is to protect you from slippage. If the actual output amount is less than this, the transaction will revert.permitData
: As TOSHI does not support permit, this can only be used when selling the token. If you are selling the token, you can use thepermitData
to avoid another approve TX. If you are buying the token, this is not needed.extensionData
: Check theFarcaster Extension
section for more details on how to use the Farcaster extension. (If a token is already listed on Uniswap, the extensionData will be ignored)
/// @notice Parameters for swapping exact input amount for output token (V3) with extension support
struct ExactInputV3Params {
/// @notice The address of the input token (use address(0) for native asset)
address inputToken;
/// @notice The address of the output token (use address(0) for native asset)
address outputToken;
/// @notice The amount of input token to swap (in input token decimals)
uint256 inputAmount;
/// @notice The minimum amount of output token to receive
uint256 minOutputAmount;
/// @notice Optional permit data for the input token (can be empty)
bytes permitData;
/// @notice Additional extension specific data to be passed to the extension's `onTrade` method, check the extension's documentation for details on the expected format and content
bytes extensionData;
}
/// @notice Parameters for quoting the output amount for a given input
struct QuoteExactInputParams {
/// @notice The address of the input token (use address(0) for native asset)
address inputToken;
/// @notice The address of the output token (use address(0) for native asset)
address outputToken;
/// @notice The amount of input token to swap (in input token decimals)
uint256 inputAmount;
}
/// @notice Swap exact input amount for output token (V3) with extension support
/// @param params The swap parameters including extension data
/// @return outputAmount The amount of output token received
/// @dev Similar to swapExactInput but with extension support. Extension hooks will be called if the token uses an extension
function swapExactInputV3(ExactInputV3Params calldata params) external payable returns (uint256 outputAmount);
/// @notice Quote the output amount for a given input
/// @param params The quote parameters
/// @return outputAmount The quoted output amount
/// @dev refer to the swapExactInput method for the scenarios
function quoteExactInput(QuoteExactInputParams calldata params) external returns (uint256 outputAmount);
You can always first approve your token to be spent by the Portal contract before calling the swapExactInputV3
method. However, if you want to avoid another approve TX, you can use the permitData
to approve the Portal contract to spend your token. And here is an example on how to generate the permitData
for the TOSHI token:
async function generatePermitData(
tokenAddress: Address,
amount: bigint
): Promise<Hex>{
if (!user || !publicClient) {
throw new Error("User or public client not available");
}
const tokenContract = getContract({
abi: [
{
type: "function",
name: "name",
inputs: [],
outputs: [{ name: "", type: "string" }],
stateMutability: "view"
},
{
type: "function",
name: "nonces",
inputs: [{ name: "", type: "address" }],
outputs: [{ name: "", type: "uint256" }],
stateMutability: "view"
}
],
address: tokenAddress,
client: publicClient,
});
const nonce = await tokenContract.read.nonces([user]) as bigint;
const name = await tokenContract.read.name() as string;
const deadline = BigInt(Date.now() + 10 * 60 * 1000);
const sig = await signTypedDataAsync({
domain: {
name,
version: "1",
chainId,
verifyingContract: tokenAddress
},
types: {
Permit: [
{ name: "owner", type: "address" },
{ name: "spender", type: "address" },
{ name: "value", type: "uint256" },
{ name: "nonce", type: "uint256" },
{ name: "deadline", type: "uint256" }
]
},
primaryType: "Permit",
message: {
owner: user,
spender: PORTAL,
value: amount,
nonce,
deadline,
}
});
// Parse signature into r, s, v
const { r, s, v } = parseSignature(sig) as {
r: `0x${string}`;
s: `0x${string}`;
v: bigint;
yParity: number;
};
// Encode permit data
const permitData = encodeAbiParameters([
{ name: "owner", type: "address" },
{ name: "spender", type: "address" },
{ name: "value", type: "uint256" },
{ name: "deadline", type: "uint256" },
{ name: "v", type: "uint8" },
{ name: "r", type: "bytes32" },
{ name: "s", type: "bytes32" }
], [user, PORTAL, amount, deadline, Number(v), r, s]);
return permitData;
}
3. The Farcaster Extension
The Farcaster Extension can only be applied to token using TOSHI as the payment token for now.
The farcaster extension allows you to optionally attribute your actions (either launching a token or trading a token) to your Farcaster account (or the coming BASE app profile). If you are trading or launching the token in our mini app, the Farcaster extension will be automatically enabled for you.
Besides trading and launching tokens in mini app, you can also use our verify tool to bind any of your EVM address to your farcaster account. Toshi Mart will prefer showing your Farcaster account if you have bound your EVM address to it.
3.1 Bind Your EVM Address To Your Farcaster Account
When you connect your EVM address (including Farcaster Wallet) to Toshi Mart Mini App and trade or launch a token once, your EVM address will be automatically bound to your Farcaster account.
And we also allows you to programmatically bind your EVM address to your Farcaster account. To do this, you need to get a farcaster proof first.
Here is how you can do it:
Open the Flap Farcaster Verify Mini App: https://farcaster.xyz/miniapps/i_eTs1A8VUeO/verify
Then you can either switch the wallet that you want to use in your program or directly input an EVM address you want to use in your program. And do not forget to check the
mainnet
tab or you will get a testnet proof. Then click the “Get Flap Farcaster Verification Proof” button

Optionally, you may see the following image. In such case, you need to open your farcaster mobile app to approve the authentification.

Then you will see the proof returned. Then you can use the proof along with the specified address. When you interact with our smart contract with that address, our indexer will attribute those actions to your farcaster account.

Here is an example of launching token with Farcaster extension, the extension data is the abi encoding of the OnTokenCreationData
struct, which contains the fid
of your Farcaster account, a farcasterOnly
flag (which is 1 for farcaster only mode), and the proof
you obtained earlier.
// keccak256("flap.extension.farcaster.v1")
const farcaster_ext_id = "0xde2fc1e2b9af1e3b4c78aa33ffb29301a87cd6208fff491445490b8df8a4effa" as Hex;
const params = {
name: "Farcaster Only Demo Token",
symbol: "FCDEMO",
meta: metaCid,
dexThresh: DexThreshType.FOUR_FIFTHS,
salt: salt,
taxRate: 0, // can only be zero for now
migratorType: MigratorType.V3_MIGRATOR,
quoteToken: toshiToken,
quoteAmt: parseEther("0"),
beneficiary: account.address,
permitData: "0x",
extensionID: farcaster_ext_id,
extensionData: encodeAbiParameters(
[
{
name: "OnTokenCreationData",
type: "tuple",
components: [
{ name: "fid", type: "uint32" },
{ name: "farcasterOnly", type: "uint8" },
{ name: "proof", type: "bytes" }
]
}
],
[
{
fid: proof.fid,
farcasterOnly: 0, // can only be zero since restriction is removed in production release
proof: proof.proof as Hex,
}
]
)
};
And here is an example of trading a token with Farcaster extension, the extension data is the abi encoding of the OnTradeData
struct, which contains the fid
of your Farcaster account and the proof
you obtained earlier.
const swapParams = {
inputToken: FlapBaseSepoliaConfig.toshi,
outputToken: TEST_TOKEN_ADDRESS,
inputAmount: TRADE_AMOUNT,
minOutputAmount: minOutputAmount,
permitData: "0x" as Hex, // toshi does not support permit
// You can use empty "0x" hex if the token is not farcaster only
extensionData: encodeAbiParameters(
[
{
name: "OnTradeData",
type: "tuple",
components: [
{ name: "fid", type: "uint32" },
{ name: "proof", type: "bytes" }
]
}
],
[
{
fid: proof.fid,
proof: proof.proof as Hex,
}
]
)
};
3.2 Profile Merging
If you have bound multiple EVM addresses to the same Farcaster account, they will be merged into a single profile in Toshi Mart Mini App. This means that all your actions (trading, launching tokens, etc.) will be attributed to the same Farcaster account, regardless of which EVM address you used to perform the action.
4. How To Build An Indexer For Toshi Mart Tokens
4.1 Index Token Creation Events
For backward compatibility, each newly launched token will emit one or more events rather than a single event, these events are emitted from the Portal Contract:
TokenCreated
: Every token launch will emit aTokenCreated
event.TokenCurveSet
: (optional), if a token launch does not emit this event, its curve is the first one in theCurveType
enum, (i.e, the one with a value = 0)TokenDexSupplyThreshSet
: (optional), if a token does not emit this event, its dex threshold is by default the first one in theDexThreshType
enum, which is 6.67e8 ether.TokenQuoteSet
: (optional), if a token does not emit this event, its quote token is the native gas token (i.e, zero address)TokenMigratorSet
: (optional), if a token does not emit this event, its Migrator type is by defaultV3_MIGRATOR
(i.e, the first one in theMigratorType
enum).FlapTokenTaxSet
: (optional), if a token does not emit this event, the tax is 0 or it is not a tax token.TokenExtensionEnabled
: emitted if only the token is created with an extension (currently, we only support farcaster extension)
/// @notice emitted when a new token is created
///
/// @param ts The timestamp of the event
/// @param creator The address of the creator
/// @param nonce The nonce of the token
/// @param token The address of the token
/// @param name The name of the token
/// @param symbol The symbol of the token
/// @param meta The meta URI of the token
event TokenCreated(
uint256 ts, address creator, uint256 nonce, address token, string name, string symbol, string meta
);
/// emitted when a token's curve is set
/// @param token The address of the token
/// @param curve The address of the curve
/// @param curveParameter The parameter of the curve
event TokenCurveSet(address token, address curve, uint256 curveParameter);
/// emitted when a token's dexSupplyThresh is set
/// @param token The address of the token
/// @param dexSupplyThresh The new dexSupplyThresh of the token
event TokenDexSupplyThreshSet(address token, uint256 dexSupplyThresh);
/// emitted when a token's implementation is set
/// @param token The address of the token
/// @param version The version of the token
event TokenVersionSet(address token, TokenVersion version);
/// @notice emitted when a token's quote token is set
/// @param token The address of the token
/// @param quoteToken The address of the quote token
event TokenQuoteSet(address token, address quoteToken);
/// @notice emitted when a token's migrator is set
/// @param token The address of the token
/// @param migratorType The migrator type
event TokenMigratorSet(address token, MigratorType migratorType);
/// @notice emitted when a new tax is set for a token
/// @param token The address of the token
/// @param tax The tax value set for the token
event FlapTokenTaxSet(address token, uint256 tax);
/// @notice emitted when a token's extension is enabled
/// @param token The address of the token
/// @param extensionID The extension ID
/// @param extensionAddress The address of the extension contract
/// @param version The version of the extension
event TokenExtensionEnabled(address token, bytes32 extensionID, address extensionAddress, uint8 version);
4.2 How To Get Token Meta and Image
As we have mentioned in the 1.1 Prepare The Metadata For Your Token
section, the metadata of a token is stored on IPFS. You can get the metadata by fetching the IPFS CID from the TokenCreated
event.
Alternatively, you can also get the metadata through the token's contract by calling the metaURI
method of the token contract. The meta
method returns the IPFS CID of the token's metadata.
interface IFlapToken {
function metaU RI() external view returns (string memory);
}
Let's take the JACK token as an example to illustrate how to get the image:
If you call the metaURI
method of the 0x8d760f4fda919a8e9f38237ee003fe8ff0ca9ef7 token, you will get the following cid: bafkreihxg3ostaaavhg7bjxmju53hzbmqr3uczsytkctqj2aqnmocdq5iy
.
You can get the meta json from any ipfs gateway. However, it would be fast to use our ipfs gateway. Our gateway is located at https://flap.mypinata.cloud/ . Such that, you can get the meta json here: https://flap.mypinata.cloud/ipfs/bafkreihxg3ostaaavhg7bjxmju53hzbmqr3uczsytkctqj2aqnmocdq5iy
.
The meta json is as follows:
{
"buy": null,
"creator": "0x315F3803d4b33F9316be52297522EA7208a52f80",
"description": "#JACKWILLTAKEUS ",
"image": "bafkreic7gc6krk32vmtvd55f3n2wavevz6hcxsyeagxppgn3p2gwphafsi",
"sell": null,
"telegram": null,
"twitter": null,
"website": null
}
Note that the image field is also a cid, which is the cid of the image. Similarly, we can get the image here: https://flap.mypinata.cloud/ipfs/bafkreic7gc6krk32vmtvd55f3n2wavevz6hcxsyeagxppgn3p2gwphafsi
.
4.2 Index Token Trade Events
When a token is traded on the bonding curve, the Portal contract will emit one of the following events:
TokenBought
: emitted when a token is bought on the bonding curve.TokenSold
: emitted when a token is sold on the bonding curve.
/// @notice emitted when a token is bought
///
/// @param ts The timestamp of the event
/// @param token The address of the token
/// @param buyer The address of the buyer
/// @param amount The amount of tokens bought
/// @param eth The amount of quote token (ETH / TOSHI) spent
/// @param fee The amount of quote token (ETH / TOSHI) spent on fee
/// @param postPrice The price of the token after this trade
event TokenBought(
uint256 ts, address token, address buyer, uint256 amount, uint256 eth, uint256 fee, uint256 postPrice
);
/// @notice emitted when a token is sold
///
/// @param ts The timestamp of the event
/// @param token The address of the token
/// @param seller The address of the seller
/// @param amount The amount of tokens sold
/// @param eth The amount of quote token (ETH / TOSHI) received
/// @param fee The amount of quote token (ETH / TOSHI) deducted as a fee
/// @param postPrice The price of the token after this trade
event TokenSold(
uint256 ts, address token, address seller, uint256 amount, uint256 eth, uint256 fee, uint256 postPrice
);
Besides, the following event will emmited:
/// @notice emitted when the circulating supply of a token changes
/// @param token The address of the token
/// @param newSupply The new circulating supply
event FlapTokenCirculatingSupplyChanged(address token, uint256 newSupply);
With the FlapTokenCirculatingSupplyChanged
event, you can track the circulating supply of a token and make use of it to get a quote off-chain with the bonding curve equation.
4.3 Index Token Migration Events
When a token is migrated to DEX, the Portal contract will emit the following events:
/// @notice emitted when migrating to DEX
/// @param token The address of the token
/// @param pool The address of the pool
/// @param amount The amount of token added to DEX
/// @param eth The amount of quote token (ETH / TOSHI) added to DEX
event LaunchedToDEX(address token, address pool, uint256 amount, uint256 eth);
Last updated