Let’s create tokens that can be traded only by certain whitelisted addresses and that cannot be sent to a non-whitelisted ones.
Model
The issuer (account) stores asset-whitelist pairs:
data: [
{
key: 'asset id',
type: 'string',
value: 'whitelist public key'
},
…
]
The whitelist (smart account) stores addresses with their statuses (true/false):
data: [
{
key: 'address',
type: 'boolean',
value: 'status'
},
…
]
The regulated token takes data from his issuer, then checks if transaction sender/recipient is in the whitelist.
The issuer can store multiple asset-whitelist pairs, and can also use one whitelist for several assets.
Code
The whitelist has following script (it just accepts data transactions signed by admin, multisignature account can be used):
let adminPublicKey = base58'adminPK'
sigVerify(tx.bodyBytes, tx.proofs[0], adminPublicKey)
The smart asset script is:
let adminPublicKey = base58'adminPK'
let adminAddress = addressFromPublicKey(adminPublicKey)
match tx {
case allow: ExchangeTransaction | TransferTransaction =>
let assetId = match allow {
case e: ExchangeTransaction =>
e.sellOrder.assetPair.amountAsset
case t: TransferTransaction =>
t.assetId
}
let assetIdString = toBase58String(extract(assetId))
let whitelistPK = extract(getString(adminAddress, assetIdString))
let whitelistAddress = extract(addressFromPublicKey(fromBase58String(whitelistPK)))
let senderAddress = match allow {
case e: ExchangeTransaction =>
e.sellOrder.sender
case t: TransferTransaction =>
t.sender
}
let recipientAddress = match allow {
case t: TransferTransaction =>
addressFromRecipient(t.recipient)
case _ => throw()
}
let senderAccepted = getBoolean(whitelistAddress, toBase58String(senderAddress.bytes))
let recipientAccepted = getBoolean(whitelistAddress, toBase58String(recipientAddress.bytes))
match allow {
case e: ExchangeTransaction =>
if (!isDefined(senderAccepted))
then throw()
else extract(senderAccepted)
case t: TransferTransaction =>
if (!isDefined(senderAccepted) || !isDefined(recipientAccepted))
then throw()
else extract(senderAccepted) && extract(recipientAccepted)
}
case _ => false
}
It includes the following steps:
- obtaining the whitelist public key from the issuer’s data
- transaction sender/recipient validation