Bot Signaling

Authorized apps can signal addresses they ban on their platform (e.g., looters, bots, scammers), helping the DAO and other apps to recognize and protect against them.

VeBetterDAO or other selected apps can reset the signal counter if a user is wrongly identified as a bot.

Endpoints

Other apps or contracts can interact with the Bot Signalling module through the following functions of the VePassport contract:

  interface IVeBetterPassport {
    ...
    function signalUser(address _user) external;
    function signalUserWithReason(address _user, string memory reason) external;
    function signaledCounter(address _user) external view returns (uint256);
    function signalingThreshold() external view returns (uint256);
    function appTotalSignalsCounter(bytes32 app) external view returns (uint256);
    ...
  }

Threshold

Any app can call the signaledCounter function to get how many times a user was signalled and can decide on their own how to interpret that value.

When calling the isPerson function though, the signalled counter will be compared to a threshold set in our contract, currently set to 2. For example, if the address was signalled more than 2 times, it will not pass the personhood check.

Snippet

The following is a snippet of how to signal addresses by using the vechain SDK.

import {
  ThorClient,
  ProviderInternalBaseWallet,
  VeChainProvider,
} from '@vechain/sdk-network';
import { ErrorDecoder } from 'ethers-decode-error';
import passportAbi from './passport.json' assert { type: 'json' };

// get passport contract with signer from a helper function
const passport = await getPassportContract();

// what to signal
const addressToSignal = '0x0000000000000000000000000000000000000000';
const reason = 'test';
console.log('Address to signal is', addressToSignal, 'for', reason);

// log current signal count
const [counter] = await passport.read.signaledCounter(addressToSignal);
console.log('Signals received for address are', counter);

// send a signal
const tx = await passport.transact.signalUserWithReason(
  addressToSignal,
  reason
);

console.log('Signal sent in tx', tx.id);

async function getPassportContract() {
  // config sender
  const privateKey =
    '0x09b76a9e3c0f154ca2c6f9b9580ad5f6771493866553df98b10c38ddce987847';
  const address = '0x00351f449190a9C2A41e6989c98fe5fC5eB50000';
  const wallet = new ProviderInternalBaseWallet([
    { privateKey: Buffer.from(privateKey.slice(2), 'hex'), address },
  ]);

  // connect to network
  const thor = ThorClient.at('https://mainnet.vechain.org');

  const provider = new VeChainProvider(
    // Thor client used by the provider
    thor,

    // Internal wallet used by the provider (needed to call the getSigner() method)
    wallet,

    // Enable fee delegation
    false
  );

  const signer = await provider.getSigner(address);

  // contract config
  const passport = thor.contracts.load(
    // VePassport address
    '0x35a267671d8EDD607B2056A9a13E7ba7CF53c8b3',

    // the interface definition
    passportAbi,

    // origin signing transactions
    signer
  );

  return passport;
}

Last updated