# Treekipedia ResearchLogSchema
https://base-sepolia.easscan.org/schema/view/0x879ed82d38bd26318e55e4803c5699f3191e3e9ca2ffbf75d0cdf16524e4d9d3
```
import { EAS, SchemaEncoder } from "@ethereum-attestation-service/eas-sdk";
const easContractAddress = "0x4200000000000000000000000000000000000021";
const schemaUID = "0x879ed82d38bd26318e55e4803c5699f3191e3e9ca2ffbf75d0cdf16524e4d9d3";
const eas = new EAS(easContractAddress);
// Signer must be an ethers-like signer.
await eas.connect(signer);
// Initialize SchemaEncoder with the schema string
const schemaEncoder = new SchemaEncoder("uint256 researchLogID,address triggerWallet,string scientificName,string speciesUID,string[] speciesURL,string llmModel,string ipfsCID,uint16 numberInsights,uint16 numberCitations");
const encodedData = schemaEncoder.encodeData([
{ name: "researchLogID", value: "0", type: "uint256" }
{ name: "triggerWallet", value: "0x0000000000000000000000000000000000000000", type: "address" }
{ name: "scientificName", value: "", type: "string" }
{ name: "speciesUID", value: "", type: "string" }
{ name: "speciesURL", value: [], type: "string[]" }
{ name: "llmModel", value: "", type: "string" }
{ name: "ipfsCID", value: "", type: "string" }
{ name: "numberInsights", value: "0", type: "uint16" }
{ name: "numberCitations", value: "0", type: "uint16" }
]);
const tx = await eas.attest({
schema: schemaUID,
data: {
recipient: "0x0000000000000000000000000000000000000000",
expirationTime: 0,
revocable: true, // Be aware that if your schema is not revocable, this MUST be false
data: encodedData,
},
});
const newAttestationUID = await tx.wait();
console.log("New attestation UID:", newAttestationUID);
```
# Resolver Contracts
### Attester
This resolver ensures that an attestation is created by a specific attester. It's like a VIP pass, where only a particular entity is allowed to attest.
```
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import { SchemaResolver } from "../SchemaResolver.sol";
import { IEAS, Attestation } from "../../IEAS.sol";
/// @title AttesterResolver
/// @notice A sample schema resolver that checks whether the attestation is from a specific attester.
contract AttesterResolver is SchemaResolver {
address private immutable _targetAttester;
constructor(IEAS eas, address targetAttester) SchemaResolver(eas) {
_targetAttester = targetAttester;
}
function onAttest(Attestation calldata attestation, uint256 /*value*/) internal view override returns (bool) {
return attestation.attester == _targetAttester;
}
function onRevoke(Attestation calldata /*attestation*/, uint256 /*value*/) internal pure override returns (bool) {
return true;
}
}
```
### Expiration Time
This resolver checks if an attestation's expiration time meets a certain condition. Think of it as a "best before" date for attestations.
```
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import { SchemaResolver } from "../SchemaResolver.sol";
import { IEAS, Attestation } from "../../IEAS.sol";
/// @title ExpirationTimeResolver
/// @notice A sample schema resolver that checks whether the expiration time is later than a specific timestamp.
contract ExpirationTimeResolver is SchemaResolver {
uint256 private immutable _validAfter;
constructor(IEAS eas, uint256 validAfter) SchemaResolver(eas) {
_validAfter = validAfter;
}
function onAttest(Attestation calldata attestation, uint256 /*value*/) internal view override returns (bool) {
return attestation.expirationTime >= _validAfter;
}
function onRevoke(Attestation calldata /*attestation*/, uint256 /*value*/) internal pure override returns (bool) {
return true;
}
}
```
### Paying Resolver
This resolver facilitates payments to attesters when they create an attestation. It's a way to incentivize or reward certain attestations.
```
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
import { SchemaResolver } from "../SchemaResolver.sol";
import { IEAS, Attestation } from "../../IEAS.sol";
/// @title PayingResolver
/// @notice A sample schema resolver that pays attesters (and expects the payment to be returned during revocations).
contract PayingResolver is SchemaResolver {
using Address for address payable;
error InvalidValue();
uint256 private immutable _incentive;
constructor(IEAS eas, uint256 incentive) SchemaResolver(eas) {
_incentive = incentive;
}
function isPayable() public pure override returns (bool) {
return true;
}
function onAttest(Attestation calldata attestation, uint256 value) internal override returns (bool) {
if (value > 0) {
return false;
}
payable(attestation.attester).transfer(_incentive);
return true;
}
function onRevoke(Attestation calldata attestation, uint256 value) internal override returns (bool) {
if (value < _incentive) {
return false;
}
if (value > _incentive) {
payable(address(attestation.attester)).sendValue(value - _incentive);
}
return true;
}
}
```
### Recipient Resolver
Ensures an attestation is made to a specific recipient. It's like sending a letter, where only the intended recipient should receive it.
```
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import { SchemaResolver } from "../SchemaResolver.sol";
import { IEAS, Attestation } from "../../IEAS.sol";
/// @title RecipientResolver
/// @notice A sample schema resolver that checks whether the attestation is to a specific recipient.
contract RecipientResolver is SchemaResolver {
address private immutable _targetRecipient;
constructor(IEAS eas, address targetRecipient) SchemaResolver(eas) {
_targetRecipient = targetRecipient;
}
function onAttest(Attestation calldata attestation, uint256 /*value*/) internal view override returns (bool) {
return attestation.recipient == _targetRecipient;
}
function onRevoke(Attestation calldata /*attestation*/, uint256 /*value*/) internal pure override returns (bool) {
return true;
}
}
```
### Token Resolver
Checks if a specific amount of tokens has been approved for an attestation. It integrates token transactions into the attestation process.
```
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { SchemaResolver } from "../SchemaResolver.sol";
import { IEAS, Attestation } from "../../IEAS.sol";
/// @title TokenResolver
/// @notice A sample schema resolver that checks whether a specific amount of tokens was approved to be included in an attestation.
contract TokenResolver is SchemaResolver {
using SafeERC20 for IERC20;
error InvalidAllowance();
IERC20 private immutable _targetToken;
uint256 private immutable _targetAmount;
constructor(IEAS eas, IERC20 targetToken, uint256 targetAmount) SchemaResolver(eas) {
_targetToken = targetToken;
_targetAmount = targetAmount;
}
function onAttest(Attestation calldata attestation, uint256 /*value*/) internal view override returns (bool) {
if (_targetToken.allowance(attestation.attester, address(this)) < _targetAmount) {
revert InvalidAllowance();
}
return true;
}
function onRevoke(Attestation calldata /*attestation*/, uint256 /*value*/) internal pure override returns (bool) {
return true;
}
}
```
### Value Resolver
Ensures that an attestation is accompanied by a specific amount of ETH. It's like paying a fee or deposit for the attestation.
```
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import { SchemaResolver } from "../SchemaResolver.sol";
import { IEAS, Attestation } from "../../IEAS.sol";
/// @title ValueResolver
/// @notice A sample schema resolver that checks whether a specific amount of ETH was sent with an attestation.
contract ValueResolver is SchemaResolver {
uint256 private immutable _targetValue;
constructor(IEAS eas, uint256 targetValue) SchemaResolver(eas) {
_targetValue = targetValue;
}
function isPayable() public pure override returns (bool) {
return true;
}
function onAttest(Attestation calldata /*attestation*/, uint256 value) internal view override returns (bool) {
return value == _targetValue;
}
function onRevoke(Attestation calldata /*attestation*/, uint256 /*value*/) internal pure override returns (bool) {
return true;
}
}
```