编译器
0.8.13+commit.abaa5c0e
文件 1 的 9:AutomationBot.sol
pragma solidity ^0.8.0;
import "./interfaces/ManagerLike.sol";
import "./interfaces/ICommand.sol";
import "./interfaces/BotLike.sol";
import "./ServiceRegistry.sol";
import "./McdUtils.sol";
contract AutomationBot {
struct TriggerRecord {
bytes32 triggerHash;
uint256 cdpId;
}
string private constant CDP_MANAGER_KEY = "CDP_MANAGER";
string private constant AUTOMATION_BOT_KEY = "AUTOMATION_BOT";
string private constant AUTOMATION_EXECUTOR_KEY = "AUTOMATION_EXECUTOR";
string private constant MCD_UTILS_KEY = "MCD_UTILS";
mapping(uint256 => TriggerRecord) public activeTriggers;
uint256 public triggersCounter = 0;
ServiceRegistry public immutable serviceRegistry;
address public immutable self;
constructor(ServiceRegistry _serviceRegistry) {
serviceRegistry = _serviceRegistry;
self = address(this);
}
modifier auth(address caller) {
require(
serviceRegistry.getRegisteredService(AUTOMATION_EXECUTOR_KEY) == caller,
"bot/not-executor"
);
_;
}
modifier onlyDelegate() {
require(address(this) != self, "bot/only-delegate");
_;
}
function validatePermissions(
uint256 cdpId,
address operator,
ManagerLike manager
) private view {
require(isCdpOwner(cdpId, operator, manager), "bot/no-permissions");
}
function isCdpAllowed(
uint256 cdpId,
address operator,
ManagerLike manager
) public view returns (bool) {
address cdpOwner = manager.owns(cdpId);
return (manager.cdpCan(cdpOwner, cdpId, operator) == 1) || (operator == cdpOwner);
}
function isCdpOwner(
uint256 cdpId,
address operator,
ManagerLike manager
) private view returns (bool) {
return (operator == manager.owns(cdpId));
}
function getCommandAddress(uint256 triggerType) public view returns (address) {
bytes32 commandHash = keccak256(abi.encode("Command", triggerType));
address commandAddress = serviceRegistry.getServiceAddress(commandHash);
return commandAddress;
}
function getTriggersHash(
uint256 cdpId,
bytes memory triggerData,
address commandAddress
) private view returns (bytes32) {
bytes32 triggersHash = keccak256(
abi.encodePacked(cdpId, triggerData, serviceRegistry, commandAddress)
);
return triggersHash;
}
function checkTriggersExistenceAndCorrectness(
uint256 cdpId,
uint256 triggerId,
address commandAddress,
bytes memory triggerData
) private view {
bytes32 triggersHash = activeTriggers[triggerId].triggerHash;
require(
triggersHash != bytes32(0) &&
triggersHash == getTriggersHash(cdpId, triggerData, commandAddress),
"bot/invalid-trigger"
);
}
function checkTriggersExistenceAndCorrectness(uint256 cdpId, uint256 triggerId) private view {
require(activeTriggers[triggerId].cdpId == cdpId, "bot/invalid-trigger");
}
function addRecord(
uint256 cdpId,
uint256 triggerType,
uint256 replacedTriggerId,
bytes memory triggerData
) external {
ManagerLike manager = ManagerLike(serviceRegistry.getRegisteredService(CDP_MANAGER_KEY));
address commandAddress = getCommandAddress(triggerType);
require(
ICommand(commandAddress).isTriggerDataValid(cdpId, triggerData),
"bot/invalid-trigger-data"
);
require(isCdpAllowed(cdpId, msg.sender, manager), "bot/no-permissions");
triggersCounter = triggersCounter + 1;
activeTriggers[triggersCounter] = TriggerRecord(
getTriggersHash(cdpId, triggerData, commandAddress),
cdpId
);
if (replacedTriggerId != 0) {
require(
activeTriggers[replacedTriggerId].cdpId == cdpId,
"bot/trigger-removal-illegal"
);
activeTriggers[replacedTriggerId] = TriggerRecord(0, 0);
emit TriggerRemoved(cdpId, replacedTriggerId);
}
emit TriggerAdded(triggersCounter, commandAddress, cdpId, triggerData);
}
function removeRecord(
uint256 cdpId,
uint256 triggerId
) external {
address managerAddress = serviceRegistry.getRegisteredService(CDP_MANAGER_KEY);
require(isCdpAllowed(cdpId, msg.sender, ManagerLike(managerAddress)), "bot/no-permissions");
checkTriggersExistenceAndCorrectness(cdpId, triggerId);
activeTriggers[triggerId] = TriggerRecord(0, 0);
emit TriggerRemoved(cdpId, triggerId);
}
function addTrigger(
uint256 cdpId,
uint256 triggerType,
uint256 replacedTriggerId,
bytes memory triggerData
) external onlyDelegate {
ManagerLike manager = ManagerLike(serviceRegistry.getRegisteredService(CDP_MANAGER_KEY));
address automationBot = serviceRegistry.getRegisteredService(AUTOMATION_BOT_KEY);
BotLike(automationBot).addRecord(cdpId, triggerType, replacedTriggerId, triggerData);
if (!isCdpAllowed(cdpId, automationBot, manager)) {
manager.cdpAllow(cdpId, automationBot, 1);
emit ApprovalGranted(cdpId, automationBot);
}
}
function removeTrigger(
uint256 cdpId,
uint256 triggerId,
bool removeAllowance
) external onlyDelegate {
address managerAddress = serviceRegistry.getRegisteredService(CDP_MANAGER_KEY);
ManagerLike manager = ManagerLike(managerAddress);
address automationBot = serviceRegistry.getRegisteredService(AUTOMATION_BOT_KEY);
BotLike(automationBot).removeRecord(cdpId, triggerId);
if (removeAllowance) {
manager.cdpAllow(cdpId, automationBot, 0);
emit ApprovalRemoved(cdpId, automationBot);
}
emit TriggerRemoved(cdpId, triggerId);
}
function removeApproval(ServiceRegistry _serviceRegistry, uint256 cdpId) external onlyDelegate {
address approvedEntity = changeApprovalStatus(_serviceRegistry, cdpId, 0);
emit ApprovalRemoved(cdpId, approvedEntity);
}
function grantApproval(ServiceRegistry _serviceRegistry, uint256 cdpId) external onlyDelegate {
address approvedEntity = changeApprovalStatus(_serviceRegistry, cdpId, 1);
emit ApprovalGranted(cdpId, approvedEntity);
}
function changeApprovalStatus(
ServiceRegistry _serviceRegistry,
uint256 cdpId,
uint256 status
) private returns (address) {
address managerAddress = _serviceRegistry.getRegisteredService(CDP_MANAGER_KEY);
ManagerLike manager = ManagerLike(managerAddress);
address automationBot = _serviceRegistry.getRegisteredService(AUTOMATION_BOT_KEY);
require(
isCdpAllowed(cdpId, automationBot, manager) != (status == 1),
"bot/approval-unchanged"
);
validatePermissions(cdpId, address(this), manager);
manager.cdpAllow(cdpId, automationBot, status);
return automationBot;
}
function drawDaiFromVault(
uint256 cdpId,
ManagerLike manager,
uint256 daiCoverage
) internal {
address utilsAddress = serviceRegistry.getRegisteredService(MCD_UTILS_KEY);
McdUtils utils = McdUtils(utilsAddress);
manager.cdpAllow(cdpId, utilsAddress, 1);
utils.drawDebt(daiCoverage, cdpId, manager, msg.sender);
manager.cdpAllow(cdpId, utilsAddress, 0);
}
function execute(
bytes calldata executionData,
uint256 cdpId,
bytes calldata triggerData,
address commandAddress,
uint256 triggerId,
uint256 daiCoverage
) external auth(msg.sender) {
checkTriggersExistenceAndCorrectness(cdpId, triggerId, commandAddress, triggerData);
ManagerLike manager = ManagerLike(serviceRegistry.getRegisteredService(CDP_MANAGER_KEY));
drawDaiFromVault(cdpId, manager, daiCoverage);
ICommand command = ICommand(commandAddress);
require(command.isExecutionLegal(cdpId, triggerData), "bot/trigger-execution-illegal");
manager.cdpAllow(cdpId, commandAddress, 1);
command.execute(executionData, cdpId, triggerData);
activeTriggers[triggerId] = TriggerRecord(0, 0);
manager.cdpAllow(cdpId, commandAddress, 0);
require(command.isExecutionCorrect(cdpId, triggerData), "bot/trigger-execution-wrong");
emit TriggerExecuted(triggerId, cdpId, executionData);
}
event ApprovalRemoved(uint256 indexed cdpId, address approvedEntity);
event ApprovalGranted(uint256 indexed cdpId, address approvedEntity);
event TriggerRemoved(uint256 indexed cdpId, uint256 indexed triggerId);
event TriggerAdded(
uint256 indexed triggerId,
address indexed commandAddress,
uint256 indexed cdpId,
bytes triggerData
);
event TriggerExecuted(uint256 indexed triggerId, uint256 indexed cdpId, bytes executionData);
}
文件 2 的 9:BotLike.sol
pragma solidity ^0.8.0;
interface BotLike {
function addRecord(
uint256 cdpId,
uint256 triggerType,
uint256 replacedTriggerId,
bytes memory triggerData
) external;
function removeRecord(
uint256 cdpId,
uint256 triggerId
) external;
function execute(
bytes calldata executionData,
uint256 cdpId,
bytes calldata triggerData,
address commandAddress,
uint256 triggerId,
uint256 daiCoverage
) external;
}
文件 3 的 9:DSMath.sol
pragma solidity ^0.8.0;
contract DSMath {
function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x + y) >= x, "");
}
function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x - y) <= x, "");
}
function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {
require(y == 0 || (z = x * y) / y == x, "");
}
function div(uint256 x, uint256 y) internal pure returns (uint256 z) {
return x / y;
}
function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
return x <= y ? x : y;
}
function max(uint256 x, uint256 y) internal pure returns (uint256 z) {
return x >= y ? x : y;
}
function imin(int256 x, int256 y) internal pure returns (int256 z) {
return x <= y ? x : y;
}
function imax(int256 x, int256 y) internal pure returns (int256 z) {
return x >= y ? x : y;
}
uint256 internal constant WAD = 10**18;
uint256 internal constant RAY = 10**27;
function wmul(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = add(mul(x, y), WAD / 2) / WAD;
}
function rmul(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = add(mul(x, y), RAY / 2) / RAY;
}
function wdiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = add(mul(x, WAD), y / 2) / y;
}
function rdiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = add(mul(x, RAY), y / 2) / y;
}
function rpow(uint256 x, uint256 n) internal pure returns (uint256 z) {
z = n % 2 != 0 ? x : RAY;
for (n /= 2; n != 0; n /= 2) {
x = rmul(x, x);
if (n % 2 != 0) {
z = rmul(z, x);
}
}
}
}
文件 4 的 9:ICommand.sol
pragma solidity ^0.8.0;
interface ICommand {
function isTriggerDataValid(uint256 _cdpId, bytes memory triggerData)
external
view
returns (bool);
function isExecutionCorrect(uint256 cdpId, bytes memory triggerData)
external
view
returns (bool);
function isExecutionLegal(uint256 cdpId, bytes memory triggerData) external view returns (bool);
function execute(
bytes calldata executionData,
uint256 cdpId,
bytes memory triggerData
) external;
}
文件 5 的 9:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 6 的 9:ManagerLike.sol
pragma solidity ^0.8.0;
interface ManagerLike {
function cdpCan(
address owner,
uint256 cdpId,
address allowedAddr
) external view returns (uint256);
function vat() external view returns (address);
function ilks(uint256) external view returns (bytes32);
function owns(uint256) external view returns (address);
function urns(uint256) external view returns (address);
function cdpAllow(
uint256 cdp,
address usr,
uint256 ok
) external;
function frob(
uint256,
int256,
int256
) external;
function flux(
uint256,
address,
uint256
) external;
function move(
uint256,
address,
uint256
) external;
function exit(
address,
uint256,
address,
uint256
) external;
}
文件 7 的 9:Mcd.sol
pragma solidity ^0.8.0;
abstract contract IVat {
struct Urn {
uint256 ink;
uint256 art;
}
struct Ilk {
uint256 Art;
uint256 rate;
uint256 spot;
uint256 line;
uint256 dust;
}
mapping(bytes32 => mapping(address => Urn)) public urns;
mapping(bytes32 => Ilk) public ilks;
mapping(bytes32 => mapping(address => uint256)) public gem;
function can(address, address) public view virtual returns (uint256);
function dai(address) public view virtual returns (uint256);
function frob(
bytes32,
address,
address,
address,
int256,
int256
) public virtual;
function hope(address) public virtual;
function move(
address,
address,
uint256
) public virtual;
function fork(
bytes32,
address,
address,
int256,
int256
) public virtual;
}
abstract contract IGem {
function dec() public virtual returns (uint256);
function gem() public virtual returns (IGem);
function join(address, uint256) public payable virtual;
function exit(address, uint256) public virtual;
function approve(address, uint256) public virtual;
function transfer(address, uint256) public virtual returns (bool);
function transferFrom(
address,
address,
uint256
) public virtual returns (bool);
function deposit() public payable virtual;
function withdraw(uint256) public virtual;
function allowance(address, address) public virtual returns (uint256);
}
abstract contract IJoin {
bytes32 public ilk;
function dec() public view virtual returns (uint256);
function gem() public view virtual returns (IGem);
function join(address, uint256) public payable virtual;
function exit(address, uint256) public virtual;
}
abstract contract IDaiJoin {
function vat() public virtual returns (IVat);
function dai() public virtual returns (IGem);
function join(address, uint256) public payable virtual;
function exit(address, uint256) public virtual;
}
abstract contract IJug {
struct Ilk {
uint256 duty;
uint256 rho;
}
mapping(bytes32 => Ilk) public ilks;
function drip(bytes32) public virtual returns (uint256);
}
文件 8 的 9:McdUtils.sol
pragma solidity ^0.8.0;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./external/DSMath.sol";
import "./interfaces/ManagerLike.sol";
import "./interfaces/ICommand.sol";
import "./interfaces/Mcd.sol";
import "./interfaces/BotLike.sol";
import "./ServiceRegistry.sol";
contract McdUtils is DSMath {
address public immutable serviceRegistry;
IERC20 private immutable DAI;
address private immutable daiJoin;
address public immutable jug;
constructor(
address _serviceRegistry,
IERC20 _dai,
address _daiJoin,
address _jug
) {
serviceRegistry = _serviceRegistry;
DAI = _dai;
daiJoin = _daiJoin;
jug = _jug;
}
function toInt256(uint256 x) internal pure returns (int256 y) {
y = int256(x);
require(y >= 0, "int256-overflow");
}
function _getDrawDart(
address vat,
address urn,
bytes32 ilk,
uint256 wad
) internal returns (int256 dart) {
uint256 rate = IJug(jug).drip(ilk);
uint256 dai = IVat(vat).dai(urn);
if (dai < mul(wad, RAY)) {
dart = toInt256(sub(mul(wad, RAY), dai) / rate);
dart = mul(uint256(dart), rate) < mul(wad, RAY) ? dart + 1 : dart;
}
}
function drawDebt(
uint256 borrowedDai,
uint256 cdpId,
ManagerLike manager,
address sendTo
) external {
address urn = manager.urns(cdpId);
address vat = manager.vat();
manager.frob(cdpId, 0, _getDrawDart(vat, urn, manager.ilks(cdpId), borrowedDai));
manager.move(cdpId, address(this), mul(borrowedDai, RAY));
if (IVat(vat).can(address(this), daiJoin) == 0) {
IVat(vat).hope(daiJoin);
}
IJoin(daiJoin).exit(sendTo, borrowedDai);
}
}
文件 9 的 9:ServiceRegistry.sol
pragma solidity ^0.8.0;
contract ServiceRegistry {
uint256 public constant MAX_DELAY = 30 days;
mapping(bytes32 => uint256) public lastExecuted;
mapping(bytes32 => address) private namedService;
address public owner;
uint256 public requiredDelay;
modifier validateInput(uint256 len) {
require(msg.data.length == len, "registry/illegal-padding");
_;
}
modifier delayedExecution() {
bytes32 operationHash = keccak256(msg.data);
uint256 reqDelay = requiredDelay;
if (lastExecuted[operationHash] == 0 && reqDelay > 0) {
lastExecuted[operationHash] = block.timestamp;
emit ChangeScheduled(operationHash, block.timestamp + reqDelay, msg.data);
} else {
require(
block.timestamp - reqDelay > lastExecuted[operationHash],
"registry/delay-too-small"
);
emit ChangeApplied(operationHash, block.timestamp, msg.data);
_;
lastExecuted[operationHash] = 0;
}
}
modifier onlyOwner() {
require(msg.sender == owner, "registry/only-owner");
_;
}
constructor(uint256 initialDelay) {
require(initialDelay <= MAX_DELAY, "registry/invalid-delay");
requiredDelay = initialDelay;
owner = msg.sender;
}
function transferOwnership(address newOwner)
external
onlyOwner
validateInput(36)
delayedExecution
{
owner = newOwner;
}
function changeRequiredDelay(uint256 newDelay)
external
onlyOwner
validateInput(36)
delayedExecution
{
require(newDelay <= MAX_DELAY, "registry/invalid-delay");
requiredDelay = newDelay;
}
function getServiceNameHash(string memory name) external pure returns (bytes32) {
return keccak256(abi.encodePacked(name));
}
function addNamedService(bytes32 serviceNameHash, address serviceAddress)
external
onlyOwner
validateInput(68)
delayedExecution
{
require(namedService[serviceNameHash] == address(0), "registry/service-override");
namedService[serviceNameHash] = serviceAddress;
}
function updateNamedService(bytes32 serviceNameHash, address serviceAddress)
external
onlyOwner
validateInput(68)
delayedExecution
{
require(namedService[serviceNameHash] != address(0), "registry/service-does-not-exist");
namedService[serviceNameHash] = serviceAddress;
}
function removeNamedService(bytes32 serviceNameHash) external onlyOwner validateInput(36) {
require(namedService[serviceNameHash] != address(0), "registry/service-does-not-exist");
namedService[serviceNameHash] = address(0);
emit NamedServiceRemoved(serviceNameHash);
}
function getRegisteredService(string memory serviceName) external view returns (address) {
return namedService[keccak256(abi.encodePacked(serviceName))];
}
function getServiceAddress(bytes32 serviceNameHash) external view returns (address) {
return namedService[serviceNameHash];
}
function clearScheduledExecution(bytes32 scheduledExecution)
external
onlyOwner
validateInput(36)
{
require(lastExecuted[scheduledExecution] > 0, "registry/execution-not-scheduled");
lastExecuted[scheduledExecution] = 0;
emit ChangeCancelled(scheduledExecution);
}
event ChangeScheduled(bytes32 dataHash, uint256 scheduledFor, bytes data);
event ChangeApplied(bytes32 dataHash, uint256 appliedAt, bytes data);
event ChangeCancelled(bytes32 dataHash);
event NamedServiceRemoved(bytes32 nameHash);
}
{
"compilationTarget": {
"contracts/AutomationBot.sol": "AutomationBot"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 1000
},
"remappings": []
}
[{"inputs":[{"internalType":"contract ServiceRegistry","name":"_serviceRegistry","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"cdpId","type":"uint256"},{"indexed":false,"internalType":"address","name":"approvedEntity","type":"address"}],"name":"ApprovalGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"cdpId","type":"uint256"},{"indexed":false,"internalType":"address","name":"approvedEntity","type":"address"}],"name":"ApprovalRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"triggerId","type":"uint256"},{"indexed":true,"internalType":"address","name":"commandAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"cdpId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"TriggerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"triggerId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"cdpId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"executionData","type":"bytes"}],"name":"TriggerExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"cdpId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"triggerId","type":"uint256"}],"name":"TriggerRemoved","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"activeTriggers","outputs":[{"internalType":"bytes32","name":"triggerHash","type":"bytes32"},{"internalType":"uint256","name":"cdpId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"cdpId","type":"uint256"},{"internalType":"uint256","name":"triggerType","type":"uint256"},{"internalType":"uint256","name":"replacedTriggerId","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"addRecord","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"cdpId","type":"uint256"},{"internalType":"uint256","name":"triggerType","type":"uint256"},{"internalType":"uint256","name":"replacedTriggerId","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"addTrigger","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"executionData","type":"bytes"},{"internalType":"uint256","name":"cdpId","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"},{"internalType":"address","name":"commandAddress","type":"address"},{"internalType":"uint256","name":"triggerId","type":"uint256"},{"internalType":"uint256","name":"daiCoverage","type":"uint256"}],"name":"execute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"triggerType","type":"uint256"}],"name":"getCommandAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ServiceRegistry","name":"_serviceRegistry","type":"address"},{"internalType":"uint256","name":"cdpId","type":"uint256"}],"name":"grantApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"cdpId","type":"uint256"},{"internalType":"address","name":"operator","type":"address"},{"internalType":"contract ManagerLike","name":"manager","type":"address"}],"name":"isCdpAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ServiceRegistry","name":"_serviceRegistry","type":"address"},{"internalType":"uint256","name":"cdpId","type":"uint256"}],"name":"removeApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"cdpId","type":"uint256"},{"internalType":"uint256","name":"triggerId","type":"uint256"}],"name":"removeRecord","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"cdpId","type":"uint256"},{"internalType":"uint256","name":"triggerId","type":"uint256"},{"internalType":"bool","name":"removeAllowance","type":"bool"}],"name":"removeTrigger","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"self","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"serviceRegistry","outputs":[{"internalType":"contract ServiceRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"triggersCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]